【例子介绍】
delphi 生成QR码类及示例
【相关图片】
【源码结构】
{ 义乌科创计算机有限公司软件部 Dcopyboy Email:dcopyboy@tom.com QQ:445235526 添加 Usejis 参数 可在 当 Usejis :=true时 采用 日文(SHIFT JIS) 编码 反之采用机内码编码,成功解决 QRCode 汉字乱码问题。 } unit QRCode; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Clipbrd; const { 符号化モード } QR_EM_NUMERIC = 0; // 数字 QR_EM_ALNUM = 1; // 英数字: 0-9 A-Z SP $%* -./: QR_EM_8BIT = 2; // 8ビットバイト QR_EM_KANJI = 3; // 漢字 QR_EM_MAX = 4; // モード総数 { 誤り訂正レベル } QR_ECL_L = 0; // レベルL QR_ECL_M = 1; // レベルM QR_ECL_Q = 2; // レベルQ QR_ECL_H = 3; // レベルH QR_ECL_MAX = 4; // レベル総数 { モジュール値のマスク } QR_MM_DATA = $01; // 符号化データの黒モジュール QR_MM_BLACK = $02; // 印字される黒モジュール QR_MM_FUNC = $04; // 機能パターン領域(形式/型番情報を含む) { 機能パターンの定数 } QR_DIM_SEP = 4; // 分離パターンの幅 QR_DIM_FINDER = 7; // 位置検出パターンの1辺の長さ QR_DIM_ALIGN = 5; // 位置合わせパターンの1辺の長さ QR_DIM_TIMING = 6; // タイミングパターンのオフセット位置 { サイズ定数 } QR_SRC_MAX = 7089; // 入力データの最大長 QR_DIM_MAX = 177; // 1辺のモジュール数の最大値 QR_VER_MAX = 40; // 型番の最大値 QR_DWD_MAX = 2956; // データコード語の最大長(型番40/レベルL) QR_ECW_MAX = 2430; // 誤り訂正コード語の最大長(型番40/レベルH) QR_CWD_MAX = 3706; // コード語の最大長(型番40) QR_RSD_MAX = 123; // RSブロックデータコード語の最大長 QR_RSW_MAX = 68; // RSブロック誤り訂正コード語の最大長 QR_RSB_MAX = 2; // RSブロック種別の最大数 QR_MPT_MAX = 8; // マスクパターン種別総数 QR_APL_MAX = 7; // 位置合わせパターン座標の最大数 QR_FIN_MAX = 15; // 形式情報のビット数 QR_VIN_MAX = 18; // 型番情報のビット数 QR_CNN_MAX = 16; // 連結モードでのシンボルの最大表示個数 QR_PLS_MAX = 1024; // プラスモードでのシンボルの最大表示個数 { その他の定数 } NAV = 0; // 不使用(not available) PADWORD1 = $EC; // 埋め草コード語1: 11101100 PADWORD2 = $11; // 埋め草コード語2: 00010001 type { RSブロックごとの情報 } QR_RSBLOCK = record rsbnum: Integer; // RSブロック数 totalwords: Integer; // RSブロック総コード語数 datawords: Integer; // RSブロックデータコード語数 ecnum: Integer; // RSブロック誤り訂正数(不使用) end; { 誤り訂正レベルごとの情報 } QR_ECLEVEL = record datawords: Integer; // データコード語数(全RSブロック) capacity: array[0..QR_EM_MAX - 1] of Integer; // 符号化モードごとのデータ容量 nrsb: Integer; // RSブロックの種類(1または2) rsb: array[0..QR_RSB_MAX - 1] of QR_RSBLOCK; // RSブロックごとの情報 end; { 型番ごとの情報 } QR_VERTABLE = record version: Integer; // 型番 dimension: Integer; // 1辺のモジュール数 totalwords: Integer; // 総コード語数 remainedbits: Integer; // 剰余ビット数 nlen: array[0..QR_EM_MAX - 1] of Integer; // 文字数指示子のビット数 ecl: array[0..QR_ECL_MAX - 1] of QR_ECLEVEL; // 誤り訂正レベルごとの情報 aplnum: Integer; // 位置合わせパターン中心座標数 aploc: array[0..QR_APL_MAX - 1] of Integer; // 位置合わせパターン中心座標 end; PByte = ^Byte; const { αのべき表現→多項式係数の整数表現 } exp2fac: array[0..255] of Byte = ( 1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 18, 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1 ); { 多項式係数の整数表現→αのべき表現 } fac2exp: array[0..255] of Byte = ( NAV, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100, 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113, 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18, 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148, 206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182, 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61, 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, 243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24, 227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149, 188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, 171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31, 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, 203, 89, 95, 176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, 168, 80, 88, 175 ); { 誤り訂正生成多項式の第2項以降の係数表(べき表現) } gftable: array[0..QR_RSW_MAX, 0..QR_RSW_MAX - 1] of Byte = ( (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (87, 229, 146, 149, 238, 102, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (251, 67, 46, 61, 118, 70, 64, 94, 32, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (74, 152, 176, 100, 86, 100, 106, 104, 130, 218, 206, 140, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (8, 183, 61, 91, 202, 37, 51, 58, 58, 237, 140, 124, 5, 99, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (120, 104, 107, 109, 102, 161, 76, 3, 91, 191, 147, 169, 182, 194, 225, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (43, 139, 206, 78, 43, 239, 123, 206, 214, 147, 24, 99, 150, 39, 243, 163, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (215, 234, 158, 94, 184, 97, 118, 170, 79, 187, 152, 148, 252, 179, 5, 98, 96, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (17, 60, 79, 50, 61, 163, 26, 187, 202, 180, 221, 225, 83, 239, 156, 164, 212, 212, 188, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (210, 171, 247, 242, 93, 230, 14, 109, 221, 53, 200, 74, 8, 172, 98, 80, 219, 134, 160, 105, 165, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (229, 121, 135, 48, 211, 117, 251, 126, 159, 180, 169, 152, 192, 226, 228, 218, 111, 0, 117, 232, 87, 96, 227, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (173, 125, 158, 2, 103, 182, 118, 17, 145, 201, 111, 28, 165, 53, 161, 21, 245, 142, 13, 102, 48, 227, 153, 145, 218, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (168, 223, 200, 104, 224, 234, 108, 180, 110, 190, 195, 147, 205, 27, 232, 201, 21, 43, 245, 87, 42, 195, 212, 119, 242, 37, 9, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (41, 173, 145, 152, 216, 31, 179, 182, 50, 48, 110, 86, 239, 96, 222, 125, 42, 173, 226, 193, 224, 130, 156, 37, 251, 216, 238, 40, 192, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (10, 6, 106, 190, 249, 167, 4, 67, 209, 138, 138, 32, 242, 123, 89, 27, 120, 185, 80, 156, 38, 69, 171, 60, 28, 222, 80, 52, 254, 185, 220, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (111, 77, 146, 94, 26, 21, 108, 19, 105, 94, 113, 193, 86, 140, 163, 125, 58, 158, 229, 239, 218, 103, 56, 70, 114, 61, 183, 129, 167, 13, 98, 62, 129, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (200, 183, 98, 16, 172, 31, 246, 234, 60, 152, 115, 0, 167, 152, 113, 248, 238, 107, 18, 63, 218, 37, 87, 210, 105, 177, 120, 74, 121, 196, 117, 251, 113, 233, 30, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (159, 34, 38, 228, 230, 59, 243, 95, 49, 218, 176, 164, 20, 65, 45, 111, 39, 81, 49, 118, 113, 222, 193, 250, 242, 168, 217, 41, 164, 247, 177, 30, 238, 18, 120, 153, 60, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (59, 116, 79, 161, 252, 98, 128, 205, 128, 161, 247, 57, 163, 56, 235, 106, 53, 26, 187, 174, 226, 104, 170, 7, 175, 35, 181, 114, 88, 41, 47, 163, 125, 134, 72, 20, 232, 53, 35, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (250, 103, 221, 230, 25, 18, 137, 231, 0, 3, 58, 242, 221, 191, 110, 84, 230, 8, 188, 106, 96, 147, 15, 131, 139, 34, 101, 223, 39, 101, 213, 199, 237, 254, 201, 123, 171, 162, 194, 117, 50, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (190, 7, 61, 121, 71, 246, 69, 55, 168, 188, 89, 243, 191, 25, 72, 123, 9, 145, 14, 247, 1, 238, 44, 78, 143, 62, 224, 126, 118, 114, 68, 163, 52, 194, 217, 147, 204, 169, 37, 130, 113, 102, 73, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (112, 94, 88, 112, 253, 224, 202, 115, 187, 99, 89, 5, 54, 113, 129, 44, 58, 16, 135, 216, 169, 211, 36, 1, 4, 96, 60, 241, 73, 104, 234, 8, 249, 245, 119, 174, 52, 25, 157, 224, 43, 202, 223, 19, 82, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (228, 25, 196, 130, 211, 146, 60, 24, 251, 90, 39, 102, 240, 61, 178, 63, 46, 123, 115, 18, 221, 111, 135, 160, 182, 205, 107, 206, 95, 150, 120, 184, 91, 21, 247, 156, 140, 238, 191, 11, 94, 227, 84, 50, 163, 39, 34, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (232, 125, 157, 161, 164, 9, 118, 46, 209, 99, 203, 193, 35, 3, 209, 111, 195, 242, 203, 225, 46, 13, 32, 160, 126, 209, 130, 160, 242, 215, 242, 75, 77, 42, 189, 32, 113, 65, 124, 69, 228, 114, 235, 175, 124, 170, 215, 232, 133, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (116, 50, 86, 186, 50, 220, 251, 89, 192, 46, 86, 127, 124, 19, 184, 233, 151, 215, 22, 14, 59, 145, 37, 242, 203, 134, 254, 89, 190, 94, 59, 65, 124, 113, 100, 233, 235, 121, 22, 76, 86, 97, 39, 242, 200, 220, 101, 33, 239, 254, 116, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (183, 26, 201, 87, 210, 221, 113, 21, 46, 65, 45, 50, 238, 184, 249, 225, 102, 58, 209, 218, 109, 165, 26, 95, 184, 192, 52, 245, 35, 254, 238, 175, 172, 79, 123, 25, 122, 43, 120, 108, 215, 80, 128, 201, 235, 8, 153, 59, 101, 31, 198, 76, 31, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (106, 120, 107, 157, 164, 216, 112, 116, 2, 91, 248, 163, 36, 201, 202, 229, 6, 144, 254, 155, 135, 208, 170, 209, 12, 139, 127, 142, 182, 249, 177, 174, 190, 28, 10, 85, 239, 184, 101, 124, 152, 206, 96, 23, 163, 61, 27, 196, 247, 151, 154, 202, 207, 20, 61, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (82, 116, 26, 247, 66, 27, 62, 107, 252, 182, 200, 185, 235, 55, 251, 242, 210, 144, 154, 237, 176, 141, 192, 248, 152, 249, 206, 85, 253, 142, 65, 165, 125, 23, 24, 30, 122, 240, 214, 6, 129, 218, 29, 145, 127, 134, 206, 245, 117, 29, 41, 63, 159, 142, 233, 125, 148, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (107, 140, 26, 12, 9, 141, 243, 197, 226, 197, 219, 45, 211, 101, 219, 120, 28, 181, 127, 6, 100, 247, 2, 205, 198, 57, 115, 219, 101, 109, 160, 82, 37, 38, 238, 49, 160, 209, 121, 86, 11, 124, 30, 181, 84, 25, 194, 87, 65, 102, 190, 220, 70, 27, 209, 16, 89, 7, 33, 240, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (65, 202, 113, 98, 71, 223, 248, 118, 214, 94, 0, 122, 37, 23, 2, 228, 58, 121, 7, 105, 135, 78, 243, 118, 70, 76, 223, 89, 72, 50, 70, 111, 194, 17, 212, 126, 181, 35, 221, 117, 235, 11, 229, 149, 147, 123, 213, 40, 115, 6, 200, 100, 26, 246, 182, 218, 127, 215, 36, 186, 110, 106, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (45, 51, 175, 9, 7, 158, 159, 49, 68, 119, 92, 123, 177, 204, 187, 254, 200, 78, 141, 149, 119, 26, 127, 53, 160, 93, 199, 212, 29, 24, 145, 156, 208, 150, 218, 209, 4, 216, 91, 47, 184, 146, 47, 140, 195, 195, 125, 242, 238, 63, 99, 108, 140, 230, 242, 31, 204, 11, 178, 243, 217, 156, 213, 231, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (5, 118, 222, 180, 136, 136, 162, 51, 46, 117, 13, 215, 81, 17, 139, 247, 197, 171, 95, 173, 65, 137, 178, 68, 111, 95, 101, 41, 72, 214, 169, 197, 95, 7, 44, 154, 77, 111, 236, 40, 121, 143, 63, 87, 80, 253, 240, 126, 217, 77, 34, 232, 106, 50, 168, 82, 76, 146, 67, 106, 171, 25, 132, 93, 45, 105, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (247, 159, 223, 33, 224, 93, 77, 70, 90, 160, 32, 254, 43, 150, 84, 101, 190, 205, 133, 52, 60, 202, 165, 220, 203, 151, 93, 84, 15, 84, 253, 173, 160, 89, 227, 52, 199, 97, 95, 231, 52, 177, 41, 125, 137, 241, 166, 225, 118, 2, 54, 32, 82, 215, 175, 198, 43, 238, 235, 27, 101, 184, 127, 3, 5, 8, 163, 238) ); F0 = QR_MM_FUNC; F1 = (QR_MM_FUNC or QR_MM_BLACK); { 位置検出パターンのデータ } finderpattern: array[0..QR_DIM_FINDER - 1, 0..QR_DIM_FINDER - 1] of Byte = ( (F1, F1, F1, F1, F1, F1, F1), (F1, F0, F0, F0, F0, F0, F1), (F1, F0, F1, F1, F1, F0, F1), (F1, F0, F1, F1, F1, F0, F1), (F1, F0, F1, F1, F1, F0, F1), (F1, F0, F0, F0, F0, F0, F1), (F1, F1, F1, F1, F1, F1, F1) ); { 位置合わせパターンのデータ } alignpattern: array[0..QR_DIM_ALIGN - 1, 0..QR_DIM_ALIGN - 1] of Byte = ( (F1, F1, F1, F1, F1), (F1, F0, F0, F0, F1), (F1, F0, F1, F0, F1), (F1, F0, F0, F0, F1), (F1, F1, F1, F1, F1) ); { モード指示子(英字, 英数字, 8ビットバイト, 漢字) } modeid: array[0..QR_EM_MAX - 1] of Word = ($01, $02, $04, $08); { 英数字モードの符号化表 } alnumtable: array[0..127] of Shortint = ( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ); EN = QR_EM_NUMERIC; EA = QR_EM_ALNUM; E8 = QR_EM_8BIT; EK = QR_EM_KANJI; { 文字クラス表 } charclass: array[0..255] of Shortint = ( E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, EA, E8, E8, E8, EA, EA, E8, E8, E8, E8, EA, EA, E8, EA, EA, EA, // !"#$%&'()* ,-./ EN, EN, EN, EN, EN, EN, EN, EN, EN, EN, EA, E8, E8, E8, E8, E8, //0123456789:;<=>? E8, EA, EA, EA, EA, EA, EA, EA, EA, EA, EA, EA, EA, EA, EA, EA, //@ABCDEFGHIJKLMNO EA, EA, EA, EA, EA, EA, EA, EA, EA, EA, EA, E8, E8, E8, E8, E8, //PQRSTUVWXYZ[\]^_ E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, //`abcdefghijklmno E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, //pqrstuvwxyz{|}~ E8, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, EK, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8, E8 ); { qrcode作为日本人设计的规范,考虑了对于jis的优化。 比如日文(jis)是两个字节,但是实际上不需要两个,第一个字节的一部分是没有使用, qrcode压缩了这部分,变成了13位,编入kanji mode。这使得qrcode在同样的大小上编入更多的日文字符。 qrcode同样支持utf-8,这部分数据没有任何变动的,写入了byte mode。 那为何又乱码呢?首先utf-8的数据,无论生成,解析都不会错,这是肯定的。问题出在gbk上, 比如用网上流传的qrcode edit(无论中文还是日文版),在windons上生成一个包含中文的qrcode码, 则通常会乱码,因为windoes默认是用gbk,而生成器本身无法识别gbk(中文版,知识汉化界面罢了), 它会把一部分汉子的第一个字节编入kanji mode,一部分编入byte mode。 所以解析器无论怎么做格式转换都无法获取正确的数据。 至于有些工具(爱拍)我用过,确实是可以解析这种情况,我猜测是牺牲了日文, 把编入kanji mode的数据强行跟byte mode的数据整合 思路跳过对EK代码的的检测,即可支持中文 .} type { 座標データ型 } COORD = record ypos: Integer; xpos: Integer; end; const { 形式情報(2箇所)の座標(下位ビットから) } { (負数は下端/右端からのオフセット) } fmtinfopos: array[0..1, 0..QR_FIN_MAX - 1] of COORD = ( ((ypos: 0; xpos: 8), (ypos: 1; xpos: 8), (ypos: 2; xpos: 8), (ypos: 3; xpos: 8), (ypos: 4; xpos: 8), (ypos: 5; xpos: 8), (ypos: 7; xpos: 8), (ypos: 8; xpos: 8), (ypos: - 7; xpos: 8), (ypos: - 6; xpos: 8), (ypos: - 5; xpos: 8), (ypos: - 4; xpos: 8), (ypos: - 3; xpos: 8), (ypos: - 2; xpos: 8), (ypos: - 1; xpos: 8)), ((ypos: 8; xpos: - 1), (ypos: 8; xpos: - 2), (ypos: 8; xpos: - 3), (ypos: 8; xpos: - 4), (ypos: 8; xpos: - 5), (ypos: 8; xpos: - 6), (ypos: 8; xpos: - 7), (ypos: 8; xpos: - 8), (ypos: 8; xpos: 7), (ypos: 8; xpos: 5), (ypos: 8; xpos: 4), (ypos: 8; xpos: 3), (ypos: 8; xpos: 2), (ypos: 8; xpos: 1), (ypos: 8; xpos: 0)) ); { 形式情報の固定黒モジュール } fmtblackpos: COORD = (ypos: - 8; xpos: 8); { 型番情報(2箇所)の座標(下位ビットから) } { (負数は下端/右端からのオフセット) } verinfopos: array[0..1, 0..QR_VIN_MAX - 1] of COORD = ( ((ypos: - 11; xpos: 0), (ypos: - 10; xpos: 0), (ypos: - 9; xpos: 0), (ypos: - 11; xpos: 1), (ypos: - 10; xpos: 1), (ypos: - 9; xpos: 1), (ypos: - 11; xpos: 2), (ypos: - 10; xpos: 2), (ypos: - 9; xpos: 2), (ypos: - 11; xpos: 3), (ypos: - 10; xpos: 3), (ypos: - 9; xpos: 3), (ypos: - 11; xpos: 4), (ypos: - 10; xpos: 4), (ypos: - 9; xpos: 4), (ypos: - 11; xpos: 5), (ypos: - 10; xpos: 5), (ypos: - 9; xpos: 5)), ((ypos: 0; xpos: - 11), (ypos: 0; xpos: - 10), (ypos: 0; xpos: - 9), (ypos: 1; xpos: - 11), (ypos: 1; xpos: - 10), (ypos: 1; xpos: - 9), (ypos: 2; xpos: - 11), (ypos: 2; xpos: - 10), (ypos: 2; xpos: - 9), (ypos: 3; xpos: - 11), (ypos: 3; xpos: - 10), (ypos: 3; xpos: - 9), (ypos: 4; xpos: - 11), (ypos: 4; xpos: - 10), (ypos: 4; xpos: - 9), (ypos: 5; xpos: - 11), (ypos: 5; xpos: - 10), (ypos: 5; xpos: - 9)) ); { 型番情報(型番7~40について有効) } verinfo: array[0..QR_VER_MAX] of Longint = ( -1, -1, -1, -1, -1, -1, -1, $07C94, $085BC, $09A99, $0A4D3, $0BBF6, $0C762, $0D847, $0E60D, $0F928, $10B78, $1145D, $12A17, $13532, $149A6, $15683, $168C9, $177EC, $18EC4, $191E1, $1AFAB, $1B08E, $1CC1A, $1D33F, $1ED75, $1F250, $209D5, $216F0, $228BA, $2379F, $24B0B, $2542E, $26A64, $27541, $28C69 ); { バイナリデータ } BinaryData: set of Byte = [$00..$08, $0B, $0C, $0E..$1F, $A1..$FF]; { 漢字データ } Kanji1Data: set of Byte = [$81..$9F, $E0..$EB]; // 1バイト目 Kanji2Data: set of Byte = [$40..$7E, $80..$FC]; // 2バイト目 type TPictures = (picBMP, picEMF, picWMF); TLocation = (locLeft, locCenter, locRight); TQRMode = (qrSingle, qrConnect, qrPlus); TNumbering = (nbrNone, nbrHead, nbrTail, nbrIfVoid); TNotifyWatchEvent = procedure(Sender: TObject; Watch: Boolean) of object; { TQRCode クラス } TQRCode = class(TImage) private { Private 宣言 } FCode: string; FMemory: PChar; FLen: Integer; FBinary: Boolean; FBinaryOperation: Boolean; FMode: TQRMode; FCount: Integer; FColumn: Integer; FParity: Integer; // 連結モードの場合に使用するシンボルデータのパリティ値 FNumbering: TNumbering; FCommentUp: string; FCommentUpLoc: TLocation; FCommentDown: string; FCommentDownLoc: TLocation; FSymbolLeft: Integer; FSymbolTop: Integer; FSymbolSpaceUp: Integer; FSymbolSpaceDown: Integer; FSymbolSpaceLeft: Integer; FSymbolSpaceRight: Integer; FVersion: Integer; // 型番 FEmode: Integer; // 符号化モード ,自動判定 字符集 0:数字 FEmodeR: Integer; FEclevel: Integer; // 誤り訂正レベル = 0 (误差级别0-4) FMasktype: Integer; // マスクパターン種別 -1; 自動設定 FMasktypeR: Integer; FPxmag: Integer; // 表示画素倍率 FAngle: Integer; // 回転角度 FReverse: Boolean; // 反転表示 FPBM: TStringList; // Portable Bitmap FMatch: Boolean; FComFont: TFont; FTransparent: Boolean; FSymbolColor: TColor; FBackColor: TColor; FSymbolPicture: TPictures; FSymbolEnabled: Boolean; FSymbolDebug: Boolean; // デバッグ用プロパティ FSymbolDisped: Boolean; FClearOption: Boolean; FMfCanvas: TMetafileCanvas; // メタファイル用キャンバス FWindowHandle: HWND; FNextWindowHandle: HWND; FRegistered: Boolean; FClipWatch: Boolean; // クリップボード監視用のスイッチ FWatch: Boolean; // Code が自動更新された時に True になる。 FOnChangeCode: TNotifyWatchEvent; // OnChangeCode イベントフィールド FOnPaintSymbol: TNotifyWatchEvent; // OnPaintSymbol イベントフィールド FOnPaintedSymbol: TNotifyWatchEvent; // OnPaintedSymbol イベントフィールド FOnChangedCode: TNotifyWatchEvent; // OnChangedCode イベントフィールド FOnClipChange: TNotifyEvent; // OnClipChange イベントフィールド FSkip: Boolean; // 最初の OnClipChange イベントをスキップする為のフラッグ { データ領域 } vertable: array[0..QR_VER_MAX] of QR_VERTABLE; // 型番データ表 source: array[0..QR_SRC_MAX - 1] of Byte; // 入力データ領域 dataword: array[0..QR_DWD_MAX - 1] of Byte; // データコード語領域 ecword: array[0..QR_ECW_MAX - 1] of Byte; // 誤り訂正コード語領域 codeword: array[0..QR_CWD_MAX - 1] of Byte; // シンボル配置用コード語領域 rswork: array[0..QR_RSD_MAX - 1] of Byte; // RS符号計算用作業領域 symbol: array[0..QR_DIM_MAX - 1, 0..QR_DIM_MAX - 1] of Byte; // シンボルデータ領域 offsets: array[0..QR_PLS_MAX] of Integer; // 各シンボルデータオフセット値格納領域 { その他の大域変数 } srclen: Integer; // 入力データのバイト長 dwpos: Integer; // データコード語の追加バイト位置 dwbit: Integer; // データコード語の追加ビット位置 xpos, ypos: Integer; // モジュールを配置する座標位置 xdir, ydir: Integer; // モジュール配置の移動方向 icount: Integer; // 表示中のシンボルのカウンタ値(1 ~ QR_PLS_MAX) FUsejis: boolean; //使用jis优化,dcopyboy function GetData(Index: Integer): Byte; function GetOffset(Index: Integer): Integer; function GetSymbolWidth: Integer; function GetSymbolWidthS: Integer; function GetSymbolWidthA: Integer; function GetSymbolHeight: Integer; function GetSymbolHeightS: Integer; function GetSymbolHeightA: Integer; function GetQuietZone: Integer; function GetCapacity: Integer; function GetPBM: TStringList; procedure SetCode(const Value: string); procedure SetData(Index: Integer; const Value: Byte); procedure SetBinaryOperation(const Value: Boolean); procedure SetMode(const Value: TQRMode); procedure SetCount(const Value: Integer); procedure SetColumn(const Value: Integer); procedure SetNumbering(const Value: TNumbering); procedure SetCommentUp(const Value: string); procedure SetCommentUpLoc(const Value: TLocation); procedure SetCommentDown(const Value: string); procedure SetCommentDownLoc(const Value: TLocation); procedure SetSymbolLeft(const Value: Integer); procedure SetSymbolTop(const Value: Integer); procedure SetSymbolSpaceUp(const Value: Integer); procedure SetSymbolSpaceDown(const Value: Integer); procedure SetSymbolSpaceLeft(const Value: Integer); procedure SetSymbolSpaceRight(const Value: Integer); procedure SetVersion(const Value: Integer); procedure SetEmode(const Value: Integer); procedure SetEclevel(const Value: Integer); procedure SetMasktype(const Value: Integer); procedure SetPxmag(const Value: Integer); procedure SetAngle(const Value: Integer); procedure SetReverse(const Value: Boolean); procedure SetMatch(const Value: Boolean); procedure SetComFont(const Value: TFont); procedure SetTransparent(const Value: Boolean); procedure SetSymbolColor(const Value: TColor); procedure SetBackColor(const Value: TColor); procedure SetSymbolPicture(const Value: TPictures); procedure SetSymbolEnabled(const Value: Boolean); procedure SetSymbolDebug(const Value: Boolean); procedure SetClearOption(const Value: Boolean); procedure SetClipWatch(const Value: Boolean); procedure SetOnClipChange(const Value: TNotifyEvent); { ローカル関数群 } procedure PaintSymbolCodeB; procedure PaintSymbolCodeM; procedure SaveToClipAsWMF(const mf: TMetafile); procedure WndClipProc(var Message: TMessage); procedure UpdateClip; procedure ClipChangeHandler(Sender: TObject); procedure RotateBitmap(Degree: Integer); procedure ReverseBitmap; function CPos(Ch: Char; const Str: string; Index: Integer): Integer; function Code2Data: Integer; function Data2Code: Integer; procedure CheckParity; procedure CheckOffset; function isData(i, j: Integer): Boolean; function isBlack(i, j: Integer): Boolean; function isFunc(i, j: Integer): Boolean; function CharClassOf(src: PByte; len: Integer): Shortint; procedure initvertable; function qrEncodeDataWordA: Integer; function qrEncodeDataWordM: Integer; procedure qrInitDataWord; function qrGetSourceRegion(src: PByte; len: Integer; var mode: Integer): Integer; function qrGetEncodedLength(mode: Integer; len: Integer): Integer; procedure qrAddDataBits(n: Integer; w: Longword); function qrRemainedDataBits: Integer; procedure qrComputeECWord; procedure qrMakeCodeWord; procedure qrFillFunctionPattern; procedure qrFillCodeWord; procedure qrInitPosition; procedure qrNextPosition; procedure qrSelectMaskPattern; procedure qrSetMaskPattern(mask: Integer); function qrEvaluateMaskPattern: Longint; procedure qrFillFormatInfo; procedure qrOutputSymbol; procedure qrOutputSymbols; protected { Protected 宣言 } { イベントメソッド宣言 } procedure ChangeCode; dynamic; procedure PaintSymbol; dynamic; procedure PaintedSymbol; dynamic; procedure ChangedCode; dynamic; procedure ClipChange; dynamic; public { Public 宣言 } procedure PaintSymbolCode; virtual; constructor Create(AOwner: TComponent); override; destructor Destroy; override; { 公開メソッド宣言 } procedure Clear; virtual; procedure CopyToClipboard; virtual; procedure PasteFromClipboard; virtual; procedure RepaintSymbol; virtual; procedure LoadFromFile(const FileName: string); procedure SaveToFile(const FileName: string); procedure LoadFromMemory(const Ptr: Pointer; Count: Integer); { プロパティ宣言 } property Data[Index: Integer]: Byte read GetData write SetData; default; property Memory: PChar read FMemory nodefault; property Offset[Index: Integer]: Integer read GetOffset; { イベント宣言 } property OnClipChange: TNotifyEvent read FOnClipChange write SetOnClipChange; published { Published 宣言(プロパティ宣言) } property Code: string read FCode write SetCode; property Len: Integer read FLen nodefault; property Binary: Boolean read FBinary nodefault; property BinaryOperation: Boolean read FBinaryOperation write SetBinaryOperation default False; property Mode: TQRMode read FMode write SetMode default qrSingle; property Count: Integer read FCount write SetCount default 1; property Column: Integer read FColumn write SetColumn default 16; property Parity: Integer read FParity nodefault; property Numbering: TNumbering read FNumbering write SetNumbering default nbrIfVoid; property CommentUp: string read FCommentUp write SetCommentUp nodefault; property CommentUpLoc: TLocation read FCommentUpLoc write SetCommentUpLoc nodefault; property CommentDown: string read FCommentDown write SetCommentDown nodefault; property CommentDownLoc: TLocation read FCommentDownLoc write SetCommentDownLoc nodefault; property Usejis: Boolean read FUsejis write FUsejis; //使用jis优化,dcopyboy property SymbolWidth: Integer read GetSymbolWidth; property SymbolWidthS: Integer read GetSymbolWidthS; property SymbolWidthA: Integer read GetSymbolWidthA; property SymbolHeight: Integer read GetSymbolHeight; property SymbolHeightS: Integer read GetSymbolHeightS; property SymbolHeightA: Integer read GetSymbolHeightA; property QuietZone: Integer read GetQuietZone; property SymbolLeft: Integer read FSymbolLeft write SetSymbolLeft nodefault; property SymbolTop: Integer read FSymbolTop write SetSymbolTop nodefault; property SymbolSpaceUp: Integer read FSymbolSpaceUp write SetSymbolSpaceUp nodefault; property SymbolSpaceDown: Integer read FSymbolSpaceDown write SetSymbolSpaceDown nodefault; property SymbolSpaceLeft: Integer read FSymbolSpaceLeft write SetSymbolSpaceLeft nodefault; property SymbolSpaceRight: Integer read FSymbolSpaceRight write SetSymbolSpaceRight nodefault; property Version: Integer read FVersion write SetVersion default 1; property Emode: Integer read FEmode write SetEmode default -1; property EmodeR: Integer read FEmodeR nodefault; property Eclevel: Integer read FEclevel write SetEclevel default 0; property Masktype: Integer read FMasktype write SetMasktype default -1; property MasktypeR: Integer read FMasktypeR nodefault; property Capacity: Integer read GetCapacity; property Pxmag: Integer read FPxmag write SetPxmag default 1; property Angle: Integer read FAngle write SetAngle default 0; property Reverse: Boolean read FReverse write SetReverse default False; property PBM: TStringList read GetPBM; property Match: Boolean read FMatch write SetMatch nodefault; property ComFont: TFont read FComFont write SetComFont stored True; property Transparent: Boolean read FTransparent write SetTransparent nodefault; property SymbolColor: TColor read FSymbolColor write SetSymbolColor default clBlack; property BackColor: TColor read FBackColor write SetBackColor default clWhite; property SymbolPicture: TPictures read FSymbolPicture write SetSymbolPicture default picBMP; property SymbolEnabled: Boolean read FSymbolEnabled write SetSymbolEnabled default True; property SymbolDebug: Boolean read FSymbolDebug write SetSymbolDebug nodefault; property SymbolDisped: Boolean read FSymbolDisped nodefault; property ClearOption: Boolean read FClearOption write SetClearOption default False; property ClipWatch: Boolean read FClipWatch write SetClipWatch default False; { イベント宣言 } property OnChangeCode: TNotifyWatchEvent read FOnChangeCode write FOnChangeCode; property OnPaintSymbol: TNotifyWatchEvent read FOnPaintSymbol write FOnPaintSymbol; property OnPaintedSymbol: TNotifyWatchEvent read FOnPaintedSymbol write FOnPaintedSymbol; property OnChangedCode: TNotifyWatchEvent read FOnChangedCode write FOnChangedCode; end; procedure Register; implementation procedure Register; begin RegisterComponents('slmis', [TQRCode]); end; constructor TQRCode.Create(AOwner: TComponent); begin inherited Create(AOwner); FCode := ''; FMemory := nil; FLen := 0; FBinary := true; FBinaryOperation := true; FMode := qrSingle; FCount := 1; FColumn := 16; icount := 1; // 表示中のシンボルのカウンタ値(1 ~ QR_PLS_MAX) ZeroMemory(@offsets, SizeOf(offsets)); FParity := 0; // 連結モードの場合に使用するシンボルデータのパリティ値 FNumbering := nbrIfVoid; FCommentUp := ''; FCommentUpLoc := locLeft; FCommentDown := ''; FCommentDownLoc := locLeft; FSymbolLeft := 0; FSymbolTop := 0; FSymbolSpaceUp := 0; FSymbolSpaceDown := 0; FSymbolSpaceLeft := 0; FSymbolSpaceRight := 0; FVersion := 1; FEmode := -1; // 自動判定 FEmodeR := FEmode; FEclevel := QR_ECL_L; // = 0(レベルL) FMasktype := -1; // 自動設定 FMasktypeR := FMasktype; FPxmag := 1; FAngle := 0; FReverse := False; FPBM := TStringList.Create; FPBM.Duplicates := dupAccept; FMatch := True; FTransparent := False; FComFont := TFont.Create; FSymbolColor := clBlack; FBackColor := clWhite; FSymbolPicture := picBMP; FSymbolEnabled := True; FSymbolDebug := False; // デバッグ用プロパティ FSymbolDisped := False; FClearOption := False; initvertable; // 2002/10/06 Modify ぜえた From Here FWindowHandle := AllocateHWnd(WndClipProc); FClipWatch := False; FWatch := False; OnClipChange := ClipChangeHandler; // メソッドをイベントにアタッチする。 FSkip := False; // 最初の OnClipChange イベントをスキップする為のフラッグ // 2002/10/06 Modify ぜえた Until Here Usejis := false;//使用jis优化,dcopyboy end; destructor TQRCode.Destroy; begin // 2002/10/06 Modify ぜえた From Here SetClipWatch(False); DeallocateHWnd(FWindowHandle); // 2002/10/06 Modify ぜえた Until Here FComFont.Free; FPBM.Free; ReallocMem(FMemory, 0); inherited Destroy; end; procedure TQRCode.ChangeCode; // イベントメソッド begin if Assigned(FOnChangeCode) and FSymbolEnabled then FOnChangeCode(Self, FWatch); // イベントハンドラの呼び出し end; procedure TQRCode.ChangedCode; // イベントメソッド begin if Assigned(FOnChangedCode) and FSymbolEnabled then FOnChangedCode(Self, FWatch); // イベントハンドラの呼び出し end; { len バイトのサイズを持つバイトデータのポインタ src が与えられた時、先頭の } { 1バイト目の実際の文字クラスを返す関数です。1バイト目が、QR_EM_KANJI } { すなわち漢字の1バイト目であっても次の2バイト目が、漢字の2バイト目で } { ない場合や len が1の場合は、QR_EM_8BIT を返します。} function TQRCode.CharClassOf(src: PByte; len: Integer): Shortint; begin Result := -1; if (src = nil) or (len < 1) then Exit; // エラー // Dcopyboy 修改,不使用Jis优化,完美支持中文 if not Usejis then begin Result := QR_EM_8BIT; Exit; end; Result := charclass[src^]; if Result = QR_EM_KANJI then begin if len = 1 then Result := QR_EM_8BIT else begin Inc(src); if not (src^ in Kanji2Data) then Result := QR_EM_8BIT; end; end; end; { Memory 内のシンボルデータを Count 個に分割し、分割後の各データの } { Memory 上のオフセット値を内部配列変数 offsets[] に格納する手続きです。} { この手続き内では、そのときの Count と Mode の値が適切であるかどうかも } { チェックし適切でなければ、適切な値にセットし直します。} procedure TQRCode.CheckOffset; var i, j: Integer; d: Integer; begin if FCount > FLen then // Count は Len よりも大きい値であってはならない。 FCount := FLen; if FCount < 1 then FCount := 1 else if FCount > QR_PLS_MAX then FCount := QR_PLS_MAX; d := FLen div FCount; // 分割後の各データの平均サイズ if (d * FCount < FLen) and ((d 1) * (FCount - 1) < FLen) then Inc(d); i := 0; // 配列 offsets[] のインデックス値(0 <= i <= Count) j := 0; // Memory 上のオフセット値(0 <= j <= Len) offsets[i] := j; // 先頭の値は、常に 0 である。 Inc(i); j := j d; while (i < FCount) and (j < FLen) do begin if (StrByteType(FMemory, j) = mbTrailByte) and (Byte(FMemory[j]) in Kanji2Data) then // 漢字の2バイト目 begin if j - 1 > offsets[i - 1] then Dec(j) else if j 1 < FLen then Inc(j) else Break; end; offsets[i] := j; Inc(i); j := j d; end; offsets[i] := FLen; // 最後尾のオフセット値は、常に Len である。 FCount := i; // 最終的に確定した Count の値 if FCount = 1 then FMode := qrSingle // シングルモード else if FCount <= QR_CNN_MAX then begin if FMode = qrSingle then // 今までシングルモードであった。 FMode := qrConnect; // 連結モード end else FMode := qrPlus; // プラスモード end; { 連結モードの場合に必要なシンボルデータのパリティ値を計算する手続きです。} { この手続きを呼び出す前には CheckOffset を呼んで Count と Mode の値を設定 } { しておく必要があります。さらにこの手続き内では、Len, Count, Mode, Column, } { offsets[] に格納された値が適正なものであるかどうかのチェックも行ないます。} procedure TQRCode.CheckParity; var i: Integer; pr: Byte; err: string; begin err := ''; if FLen < 0 then err := 'Len' else if (FCount < 1) or (FCount > QR_PLS_MAX) then err := 'Count' else if (FMode <> qrSingle) and (FMode <> qrConnect) and (FMode <> qrPlus) then err := 'Mode' else if (FColumn < 1) or (FColumn > QR_PLS_MAX) then err := 'Column' else if FLen = 0 then begin if FCount <> 1 then err := 'Count' else if FMode <> qrSingle then err := 'Mode' else if offsets[0] <> 0 then err := '0' else if offsets[1] <> 0 then err := '1'; end else begin if FCount > Flen then err := 'Count' else if (FMode = qrSingle) and (FCount <> 1) then err := 'Count' else if (FMode = qrConnect) and ((FCount < 2) or (FCount > QR_CNN_MAX)) then err := 'Count' else if (FMode = qrPlus) and ((FCount < 2) or (FCount > QR_PLS_MAX)) then err := 'Count' else if offsets[0] <> 0 then err := '0' else if offsets[FCount] <> FLen then err := IntToStr(FCount) else begin for i := 1 to FCount do begin if offsets[i] <= offsets[i - 1] then begin err := IntToStr(i); Break; end; end; end; end; if err <> '' then // 何らかのエラーがあった。 begin if err = 'Len' then i := FLen else if err = 'Count' then i := FCount else if err = 'Mode' then i := Integer(FMode) else if err = 'Column' then i := FColumn else begin i := StrToInt(err); i := offsets[i]; err := 'Offset[' err ']'; end; err := 'Illegal ' err ' : %d'; raise Exception.CreateFmt(err, [i]); end; if (FMode <> qrConnect) or (FLen div FCount > QR_SRC_MAX) then Exit; // この場合、パリティ値の計算は行なわない。 pr := Byte(FMemory[0]); // 先頭のデータ for i := 1 to FLen - 1 do pr := pr xor Byte(FMemory[i]); FParity := Integer(pr); end; { 現在 Picture が、保持しているグラフイックデータを破棄して Canvas を } { クリアーするメソッドです。このとき SymbolDisped プロパティは False } { に設定されます。} procedure TQRCode.Clear; begin if FSymbolDisped = True then FSymbolDisped := False; Picture := nil; // グラフイックデータを破棄 end; { 2002/10/06 Update ぜえた From Here } procedure TQRCode.ClipChange; // イベントメソッド begin if Assigned(FOnClipChange) then FOnClipChange(Self); // イベントハンドラの呼び出し end; procedure TQRCode.ClipChangeHandler(Sender: TObject); begin if FSkip = True then // 最初に発生した OnClipChange イベントをスキップする。 begin FSkip := False; Exit; end; FWatch := True; // クリップボード監視中にテキストデータがコピーされた。 PasteFromClipboard; FWatch := False; end; { 2002/10/06 Update ぜえた Until Here } { Code プロパティの文字列をバイトデータに変換して、シンボルデータ領域である } { Memory プロパティに格納する関数。そのときの BinaryOption プロパティの値に } { よってデータ変換の結果は異なります。戻り値は、変換されたデータのバイト数 } { です。バイナリデータを含む場合、Binary プロパティは True にセットされます。} { BinaryOption プロパティが True のときに変換エラーが生じると BinaryOption } { プロパティは強制的に False にセットされ全て通常の文字列とみなされます。} function TQRCode.Code2Data: Integer; var i, j: Integer; p1, p2: Integer; S: string; e: Integer; begin Result := Length(FCode); FBinary := False; ReallocMem(FMemory, Result 4); if Result = 0 then Exit; i := 1; // コードのインデックス j := 0; // データのインデックス S := '$00'; if FBinaryOperation = True then begin while i <= Result do begin p1 := CPos('~', FCode, i); // 最初に '~' 文字が見つかった位置 if p1 = 0 then // 見つからなかった場合は、以後全て通常の文字と見なす。 begin while i <= Result do begin FMemory[j] := FCode[i]; Inc(j); Inc(i); end; Break; end; p2 := CPos('~', FCode, p1 1); // 次に '~' 文字が見つかった位置 if (p2 = 0) or ((p2 - p1 - 1) mod 2 <> 0) then // エラー begin i := 0; // エラーのサイン Break; end; while i < p1 do begin FMemory[j] := FCode[i]; Inc(j); Inc(i); end; if p2 = p1 1 then // '~' 文字自身 begin FMemory[j] := '~'; Inc(j); end else begin i := p1 1; while i <= p2 - 2 do begin S[2] := FCode[i]; Inc(i); S[3] := FCode[i]; Inc(i); e := StrToIntDef(S, 256); if e = 256 then // エラー begin i := 0; // エラーのサイン Break; end; FMemory[j] := Chr(e); Inc(j); if Byte(e) in BinaryData then // バイナリデータを含んでいた。 FBinary := True; end; end; if i = 0 then // エラー Break; i := p2 1; end; if i = 0 then // エラー begin // エラーがあって変換不能の場合は、通常の文字列と見なす。 FBinaryOperation := False; FBinary := False; end else begin if Result <> j then begin Result := j; // データのサイズ ReallocMem(FMemory, Result 4); FMemory[Result] := Chr($00); FMemory[Result 1] := Chr($00); FMemory[Result 2] := Chr($00); FMemory[Result 3] := Chr($00); end; Exit; end; end; { BinaryOperation = False のとき } CopyMemory(FMemory, PChar(FCode), Result); FMemory[Result] := Chr($00); FMemory[Result 1] := Chr($00); FMemory[Result 2] := Chr($00); FMemory[Result 3] := Chr($00); end; procedure TQRCode.CopyToClipboard; begin { まだ一度もシンボルを表示していないか、表示に失敗した場合は、Bitmap や } { Metafile あるいはそれ以外の形式で画像が表示されている可能性もあるので } { 可能な限りコピーを試みます。} if FSymbolDisped = False then Clipboard.Assign(Picture) else if FSymbolPicture = picBMP then // ビットマップ形式でコピー Clipboard.Assign(Picture.Bitmap) else if FSymbolPicture = picEMF then // EMF形式でコピー Clipboard.Assign(Picture.Metafile) // (Win32 エンハンスドメタファイル) else // WMF形式でコピー SaveToClipAsWMF(Picture.Metafile); // (Win16 形式メタファイル) end; { 文字列 Str の Index バイト目以降で最初に文字 Ch が見つかった位置を } { 返す関数。エラーあるいは見つからなかった場合の戻り値は、0 です。} function TQRCode.CPos(Ch: Char; const Str: string; Index: Integer): Integer; var i: Integer; begin Result := 0; // エラーあるいは見つからなかった場合の戻り値 if Index < 1 then Exit; for i := Index to Length(Str) do begin if Str[i] = Ch then begin Result := i; Break; end; end; end; { Memory プロパティに格納されているシンボルデータを文字列に変換して、Code } { プロパティに格納する関数。シンボルデータがバイナリデータを含む場合は、} { Binary プロパティと BinaryOption プロパティは、True にセットされます。} { この関数を呼び出す前には、シンボルデータのサイズを Len プロパティに } { セットしておく必要があります。戻り値は形式上、シンボルデータのサイズ } { すなわち Len プロパティの値を返す様になっています。} function TQRCode.Data2Code: Integer; var i, j: Integer; P: PChar; len: Integer; S: string; inBinary: Boolean; begin { この関数を呼び出す前には、FLen の値が確定されている必要があります。} Result := FLen; FBinary := False; if Result = 0 then begin FCode := ''; Exit; end; for i := 0 to Result - 1 do begin if Byte(FMemory[i]) in BinaryData then begin FBinary := True; FBinaryOperation := True; Break; end; end; if FBinary = False then begin FCode := FMemory; // Create String Exit; end; P := nil; len := Result 8; ReallocMem(P, len); i := 0; // データのインデックス j := 0; // コードのインデックス inBinary := False; while i < Result do begin if j 8 > len then begin len := len 8; ReallocMem(P, len); end; if Byte(FMemory[i]) in BinaryData then begin if inBinary = False then begin P[j] := '~'; // Start of Binary Data Inc(j); inBinary := True; end; S := IntToHex(Byte(FMemory[i]), 2); P[j] := S[1]; Inc(j); P[j] := S[2]; Inc(j); end else begin if inBinary = True then begin P[j] := '~'; // End of Binary Data Inc(j); inBinary := False; end; P[j] := FMemory[i]; if P[j] = '~' then begin Inc(j); P[j] := '~'; end; Inc(j); end; Inc(i); end; if inBinary = True then begin P[j] := '~'; // End of Binary Data Inc(j); end; P[j] := Chr($00); // End of String P[j 1] := Chr($00); P[j 2] := Chr($00); P[j 3] := Chr($00); FCode := P; // Create String ReallocMem(P, 0); // Free Memory end; function TQRCode.GetCapacity: Integer; var em: Integer; begin em := FEmodeR; if em = -1 then em := QR_EM_ALNUM; // この場合は、暫定的に英数字モードの値を返す。 Result := vertable[FVersion].ecl[FEclevel].capacity[em] * FCount; end; function TQRCode.GetData(Index: Integer): Byte; begin if (Index < 0) or (Index >= FLen) then raise ERangeError.CreateFmt('%d is not within the valid range of %d..%d', [Index, 0, FLen - 1]); Result := Byte(FMemory[Index]); end; function TQRCode.GetOffset(Index: Integer): Integer; begin if (Index < 0) or (Index > FCount) then raise ERangeError.CreateFmt('%d is not within the valid range of %d..%d', [Index, 0, FCount]); Result := offsets[Index]; end; function TQRCode.GetPBM: TStringList; begin qrOutputSymbols; Result := FPBM; end; function TQRCode.GetQuietZone: Integer; begin Result := QR_DIM_SEP * FPxmag; end; function TQRCode.GetSymbolHeight: Integer; begin Result := (vertable[FVersion].dimension QR_DIM_SEP * 2) * FPxmag; end; function TQRCode.GetSymbolHeightA: Integer; var n: Integer; begin n := FCount div FColumn; if (FCount mod FColumn) <> 0 then Inc(n); Result := SymbolHeightS * n end; function TQRCode.GetSymbolHeightS: Integer; begin Result := FSymbolSpaceUp SymbolHeight FSymbolSpaceDown; end; function TQRCode.GetSymbolWidth: Integer; begin Result := (vertable[FVersion].dimension QR_DIM_SEP * 2) * FPxmag; end; function TQRCode.GetSymbolWidthA: Integer; var n: Integer; begin if FCount < FColumn then n := FCount else n := FColumn; Result := SymbolWidthS * n end; function TQRCode.GetSymbolWidthS: Integer; begin Result := FSymbolSpaceLeft SymbolWidth FSymbolSpaceRight; end; procedure TQRCode.initvertable; const { vertable 初期化用データ領域 } capacities: array[1..40, 0..3, 0..3] of Integer = ( // version 1 (capacities[1][0] ~capacities[1][3]) ((41, 25, 17, 10), (34, 20, 14, 8), (27, 16, 11, 7), (17, 10, 7, 4)), // version 2 ((77, 47, 32, 20), (63, 38, 26, 16), (48, 29, 20, 12), (34, 20, 14, 8)), // version 3 ((127, 77, 53, 32), (101, 61, 42, 26), (77, 47, 32, 20), (58, 35, 24, 15)), // version 4 ((187, 114, 78, 48), (149, 90, 62, 38), (111, 67, 46, 28), (82, 50, 34, 21)), // version 5 ((255, 154, 106, 65), (202, 122, 84, 52), (144, 87, 60, 37), (106, 64, 44, 27)), // version 6 ((322, 195, 134, 82), (255, 154, 106, 65), (178, 108, 74, 45), (139, 84, 58, 36)), // version 7 ((370, 224, 154, 95), (293, 178, 122, 75), (207, 125, 86, 53), (154, 93, 64, 39)), // version 8 ((461, 279, 192, 118), (365, 221, 152, 93), (259, 157, 108, 66), (202, 122, 84, 52)), // version 9 ((552, 335, 230, 141), (432, 262, 180, 111), (312, 189, 130, 80), (235, 143, 98, 60)), // version 10 ((652, 395, 271, 167), (513, 311, 213, 131), (364, 221, 151, 93), (288, 174, 119, 74)), // version 11 ((772, 468, 321, 198), (604, 366, 251, 155), (427, 259, 177, 109), (331, 200, 137, 85)), // version 12 ((883, 535, 367, 226), (691, 419, 287, 177), (489, 296, 203, 125), (374, 227, 155, 96)), // version 13 ((1022, 619, 425, 262), (796, 483, 331, 204), (580, 352, 241, 149), (427, 259, 177, 109)), // version 14 ((1101, 667, 458, 282), (871, 528, 362, 223), (621, 376, 258, 159), (468, 283, 194, 120)), // version 15 ((1250, 758, 520, 320), (991, 600, 412, 254), (703, 426, 292, 180), (530, 321, 220, 136)), // version 16 ((1408, 854, 586, 361), (1082, 656, 450, 277), (775, 470, 322, 198), (602, 365, 250, 154)), // version 17 ((1548, 938, 644, 397), (1212, 734, 504, 310), (876, 531, 364, 224), (674, 408, 280, 173)), // version 18 ((1725, 1046, 718, 442), (1346, 816, 560, 345), (948, 574, 394, 243), (746, 452, 310, 191)), // version 19 ((1903, 1153, 792, 488), (1500, 909, 624, 384), (1063, 644, 442, 272), (813, 493, 338, 208)), // version 20 ((2061, 1249, 858, 528), (1600, 970, 666, 410), (1159, 702, 482, 297), (919, 557, 382, 235)), // version 21 ((2232, 1352, 929, 572), (1708, 1035, 711, 438), (1224, 742, 509, 314), (969, 587, 403, 248)), // version 22 ((2409, 1460, 1003, 618), (1872, 1134, 779, 480), (1358, 823, 565, 348), (1056, 640, 439, 270)), // version 23 ((2620, 1588, 1091, 672), (2059, 1248, 857, 528), (1468, 890, 611, 376), (1108, 672, 461, 284)), // version 24 ((2812, 1704, 1171, 721), (2188, 1326, 911, 561), (1588, 963, 661, 407), (1228, 744, 511, 315)), // version 25 ((3057, 1853, 1273, 784), (2395, 1451, 997, 614), (1718, 1041, 715, 440), (1286, 779, 535, 330)), // version 26 ((3283, 1990, 1367, 842), (2544, 1542, 1059, 652), (1804, 1094, 751, 462), (1425, 864, 593, 365)), // version 27 ((3517, 2132, 1465, 902), (2701, 1637, 1125, 692), (1933, 1172, 805, 496), (1501, 910, 625, 385)), // version 28 ((3669, 2223, 1528, 940), (2857, 1732, 1190, 732), (2085, 1263, 868, 534), (1581, 958, 658, 405)), // version 29 ((3909, 2369, 1628, 1002), (3035, 1839, 1264, 778), (2181, 1322, 908, 559), (1677, 1016, 698, 430)), // version 30 ((4158, 2520, 1732, 1066), (3289, 1994, 1370, 843), (2358, 1429, 982, 604), (1782, 1080, 742, 457)), // version 31 ((4417, 2677, 1840, 1132), (3486, 2113, 1452, 894), (2473, 1499, 1030, 634), (1897, 1150, 790, 486)), // version 32 ((4686, 2840, 1952, 1201), (3693, 2238, 1538, 947), (2670, 1618, 1112, 684), (2022, 1226, 842, 518)), // version 33 ((4965, 3009, 2068, 1273), (3909, 2369, 1628, 1002), (2805, 1700, 1168, 719), (2157, 1307, 898, 553)), // version 34 ((5253, 3183, 2188, 1347), (4134, 2506, 1722, 1060), (2949, 1787, 1228, 756), (2301, 1394, 958, 590)), // version 35 ((5529, 3351, 2303, 1417), (4343, 2632, 1809, 1113), (3081, 1867, 1283, 790), (2361, 1431, 983, 605)), // version 36 ((5836, 3537, 2431, 1496), (4588, 2780, 1911, 1176), (3244, 1966, 1351, 832), (2524, 1530, 1051, 647)), // version 37 ((6153, 3729, 2563, 1577), (4775, 2894, 1989, 1224), (3417, 2071, 1423, 876), (2625, 1591, 1093, 673)), // version 38 ((6479, 3927, 2699, 1661), (5039, 3054, 2099, 1292), (3599, 2181, 1499, 923), (2735, 1658, 1139, 701)), // version 39 ((6743, 4087, 2809, 1729), (5313, 3220, 2213, 1362), (3791, 2298, 1579, 972), (2927, 1774, 1219, 750)), // version 40 ((7089, 4296, 2953, 1817), (5596, 3391, 2331, 1435), (3993, 2420, 1663, 1024), (3057, 1852, 1273, 784)) ); rsbs: array[0..287] of QR_RSBLOCK = ( // version 1 (rsbs[0]~rsbs[3]) (rsbnum: 1; totalwords: 26; datawords: 19; ecnum: 2), (rsbnum: 1; totalwords: 26; datawords: 16; ecnum: 4), (rsbnum: 1; totalwords: 26; datawords: 13; ecnum: 6), (rsbnum: 1; totalwords: 26; datawords: 9; ecnum: 8), // version 2 (rsbs[4]~rsbs[7]) (rsbnum: 1; totalwords: 44; datawords: 34; ecnum: 4), (rsbnum: 1; totalwords: 44; datawords: 28; ecnum: 8), (rsbnum: 1; totalwords: 44; datawords: 22; ecnum: 11), (rsbnum: 1; totalwords: 44; datawords: 16; ecnum: 14), // version 3 (rsbs[8]~rsbs[11]) (rsbnum: 1; totalwords: 70; datawords: 55; ecnum: 7), (rsbnum: 1; totalwords: 70; datawords: 44; ecnum: 13), (rsbnum: 2; totalwords: 35; datawords: 17; ecnum: 9), (rsbnum: 2; totalwords: 35; datawords: 13; ecnum: 11), // version 4 (rsbs[12]~rsbs[15]) (rsbnum: 1; totalwords: 100; datawords: 80; ecnum: 10), (rsbnum: 2; totalwords: 50; datawords: 32; ecnum: 9), (rsbnum: 2; totalwords: 50; datawords: 24; ecnum: 13), (rsbnum: 4; totalwords: 25; datawords: 9; ecnum: 8), // version 5 (rsbs[16]~rsbs[21]) (rsbnum: 1; totalwords: 134; datawords: 108; ecnum: 13), (rsbnum: 2; totalwords: 67; datawords: 43; ecnum: 12), (rsbnum: 2; totalwords: 33; datawords: 15; ecnum: 9), (rsbnum: 2; totalwords: 34; datawords: 16; ecnum: 9), (rsbnum: 2; totalwords: 33; datawords: 11; ecnum: 11), (rsbnum: 2; totalwords: 34; datawords: 12; ecnum: 11), // version 6 (rsbs[22]~rsbs[25]) (rsbnum: 2; totalwords: 86; datawords: 68; ecnum: 9), (rsbnum: 4; totalwords: 43; datawords: 27; ecnum: 8), (rsbnum: 4; totalwords: 43; datawords: 19; ecnum: 12), (rsbnum: 4; totalwords: 43; datawords: 15; ecnum: 14), // version 7 (rsbs[26]~rsbs[31]) (rsbnum: 2; totalwords: 98; datawords: 78; ecnum: 10), (rsbnum: 4; totalwords: 49; datawords: 31; ecnum: 9), (rsbnum: 2; totalwords: 32; datawords: 14; ecnum: 9), (rsbnum: 4; totalwords: 33; datawords: 15; ecnum: 9), (rsbnum: 4; totalwords: 39; datawords: 13; ecnum: 13), (rsbnum: 1; totalwords: 40; datawords: 14; ecnum: 13), // version 8 (rsbs[32]~rsbs[38]) (rsbnum: 2; totalwords: 121; datawords: 97; ecnum: 12), (rsbnum: 2; totalwords: 60; datawords: 38; ecnum: 11), (rsbnum: 2; totalwords: 61; datawords: 39; ecnum: 11), (rsbnum: 4; totalwords: 40; datawords: 18; ecnum: 11), (rsbnum: 2; totalwords: 41; datawords: 19; ecnum: 11), (rsbnum: 4; totalwords: 40; datawords: 14; ecnum: 13), (rsbnum: 2; totalwords: 41; datawords: 15; ecnum: 13), // version 9 (rsbs[39]~rsbs[45]) (rsbnum: 2; totalwords: 146; datawords: 116; ecnum: 15), (rsbnum: 3; totalwords: 58; datawords: 36; ecnum: 11), (rsbnum: 2; totalwords: 59; datawords: 37; ecnum: 11), (rsbnum: 4; totalwords: 36; datawords: 16; ecnum: 10), (rsbnum: 4; totalwords: 37; datawords: 17; ecnum: 10), (rsbnum: 4; totalwords: 36; datawords: 12; ecnum: 12), (rsbnum: 4; totalwords: 37; datawords: 13; ecnum: 12), // version 10 (rsbs[46]~rsbs[53]) (rsbnum: 2; totalwords: 86; datawords: 68; ecnum: 9), (rsbnum: 2; totalwords: 87; datawords: 69; ecnum: 9), (rsbnum: 4; totalwords: 69; datawords: 43; ecnum: 13), (rsbnum: 1; totalwords: 70; datawords: 44; ecnum: 13), (rsbnum: 6; totalwords: 43; datawords: 19; ecnum: 12), (rsbnum: 2; totalwords: 44; datawords: 20; ecnum: 12), (rsbnum: 6; totalwords: 43; datawords: 15; ecnum: 14), (rsbnum: 2; totalwords: 44; datawords: 16; ecnum: 14), // version 11 (rsbs[54]~rsbs[60]) (rsbnum: 4; totalwords: 101; datawords: 81; ecnum: 10), (rsbnum: 1; totalwords: 80; datawords: 50; ecnum: 15), (rsbnum: 4; totalwords: 81; datawords: 51; ecnum: 15), (rsbnum: 4; totalwords: 50; datawords: 22; ecnum: 14), (rsbnum: 4; totalwords: 51; datawords: 23; ecnum: 14), (rsbnum: 3; totalwords: 36; datawords: 12; ecnum: 12), (rsbnum: 8; totalwords: 37; datawords: 13; ecnum: 12), // version 12 (rsbs[61]~rsbs[68]) (rsbnum: 2; totalwords: 116; datawords: 92; ecnum: 12), (rsbnum: 2; totalwords: 117; datawords: 93; ecnum: 12), (rsbnum: 6; totalwords: 58; datawords: 36; ecnum: 11), (rsbnum: 2; totalwords: 59; datawords: 37; ecnum: 11), (rsbnum: 4; totalwords: 46; datawords: 20; ecnum: 13), (rsbnum: 6; totalwords: 47; datawords: 21; ecnum: 13), (rsbnum: 7; totalwords: 42; datawords: 14; ecnum: 14), (rsbnum: 4; totalwords: 43; datawords: 15; ecnum: 14), // version 13 (rsbs[69]~rsbs[75]) (rsbnum: 4; totalwords: 133; datawords: 107; ecnum: 13), (rsbnum: 8; totalwords: 59; datawords: 37; ecnum: 11), (rsbnum: 1; totalwords: 60; datawords: 38; ecnum: 11), (rsbnum: 8; totalwords: 44; datawords: 20; ecnum: 12), (rsbnum: 4; totalwords: 45; datawords: 21; ecnum: 12), (rsbnum: 12; totalwords: 33; datawords: 11; ecnum: 11), (rsbnum: 4; totalwords: 34; datawords: 12; ecnum: 11), // version 14 (rsbs[76]~rsbs[83]) (rsbnum: 3; totalwords: 145; datawords: 115; ecnum: 15), (rsbnum: 1; totalwords: 146; datawords: 116; ecnum: 15), (rsbnum: 4; totalwords: 64; datawords: 40; ecnum: 12), (rsbnum: 5; totalwords: 65; datawords: 41; ecnum: 12), (rsbnum: 11; totalwords: 36; datawords: 16; ecnum: 10), (rsbnum: 5; totalwords: 37; datawords: 17; ecnum: 10), (rsbnum: 11; totalwords: 36; datawords: 12; ecnum: 12), (rsbnum: 5; totalwords: 37; datawords: 13; ecnum: 12), // version 15 (rsbs[84]~rsbs[91]) (rsbnum: 5; totalwords: 109; datawords: 87; ecnum: 11), (rsbnum: 1; totalwords: 110; datawords: 88; ecnum: 11), (rsbnum: 5; totalwords: 65; datawords: 41; ecnum: 12), (rsbnum: 5; totalwords: 66; datawords: 42; ecnum: 12), (rsbnum: 5; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 7; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 11; totalwords: 36; datawords: 12; ecnum: 12), (rsbnum: 7; totalwords: 37; datawords: 13; ecnum: 12), // version 16 (rsbs[92]~rsbs[99]) (rsbnum: 5; totalwords: 122; datawords: 98; ecnum: 12), (rsbnum: 1; totalwords: 123; datawords: 99; ecnum: 12), (rsbnum: 7; totalwords: 73; datawords: 45; ecnum: 14), (rsbnum: 3; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 15; totalwords: 43; datawords: 19; ecnum: 12), (rsbnum: 2; totalwords: 44; datawords: 20; ecnum: 12), (rsbnum: 3; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 13; totalwords: 46; datawords: 16; ecnum: 15), // version 17 (rsbs[100]~rsbs[107]) (rsbnum: 1; totalwords: 135; datawords: 107; ecnum: 14), (rsbnum: 5; totalwords: 136; datawords: 108; ecnum: 14), (rsbnum: 10; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 1; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 1; totalwords: 50; datawords: 22; ecnum: 14), (rsbnum: 15; totalwords: 51; datawords: 23; ecnum: 14), (rsbnum: 2; totalwords: 42; datawords: 14; ecnum: 14), (rsbnum: 17; totalwords: 43; datawords: 15; ecnum: 14), // version 18 (rsbs[108]~rsbs[115]) (rsbnum: 5; totalwords: 150; datawords: 120; ecnum: 15), (rsbnum: 1; totalwords: 151; datawords: 121; ecnum: 15), (rsbnum: 9; totalwords: 69; datawords: 43; ecnum: 13), (rsbnum: 4; totalwords: 70; datawords: 44; ecnum: 13), (rsbnum: 17; totalwords: 50; datawords: 22; ecnum: 14), (rsbnum: 1; totalwords: 51; datawords: 23; ecnum: 14), (rsbnum: 2; totalwords: 42; datawords: 14; ecnum: 14), (rsbnum: 19; totalwords: 43; datawords: 15; ecnum: 14), // version 19 (rsbs[116]~rsbs[123]) (rsbnum: 3; totalwords: 141; datawords: 113; ecnum: 14), (rsbnum: 4; totalwords: 142; datawords: 114; ecnum: 14), (rsbnum: 3; totalwords: 70; datawords: 44; ecnum: 13), (rsbnum: 11; totalwords: 71; datawords: 45; ecnum: 13), (rsbnum: 17; totalwords: 47; datawords: 21; ecnum: 13), (rsbnum: 4; totalwords: 48; datawords: 22; ecnum: 13), (rsbnum: 9; totalwords: 39; datawords: 13; ecnum: 13), (rsbnum: 16; totalwords: 40; datawords: 14; ecnum: 13), // version 20 (rsbs[124]~rsbs[131]) (rsbnum: 3; totalwords: 135; datawords: 107; ecnum: 14), (rsbnum: 5; totalwords: 136; datawords: 108; ecnum: 14), (rsbnum: 3; totalwords: 67; datawords: 41; ecnum: 13), (rsbnum: 13; totalwords: 68; datawords: 42; ecnum: 13), (rsbnum: 15; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 5; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 15; totalwords: 43; datawords: 15; ecnum: 14), (rsbnum: 10; totalwords: 44; datawords: 16; ecnum: 14), // version 21 (rsbs[132]~rsbs[138]) (rsbnum: 4; totalwords: 144; datawords: 116; ecnum: 14), (rsbnum: 4; totalwords: 145; datawords: 117; ecnum: 14), (rsbnum: 17; totalwords: 68; datawords: 42; ecnum: 13), (rsbnum: 17; totalwords: 50; datawords: 22; ecnum: 14), (rsbnum: 6; totalwords: 51; datawords: 23; ecnum: 14), (rsbnum: 19; totalwords: 46; datawords: 16; ecnum: 15), (rsbnum: 6; totalwords: 47; datawords: 17; ecnum: 15), // version 22 (rsbs[139]~rsbs[144]) (rsbnum: 2; totalwords: 139; datawords: 111; ecnum: 14), (rsbnum: 7; totalwords: 140; datawords: 112; ecnum: 14), (rsbnum: 17; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 7; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 16; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 34; totalwords: 37; datawords: 13; ecnum: 13), // version 23 (rsbs[145]~rsbs[152]) (rsbnum: 4; totalwords: 151; datawords: 121; ecnum: 15), (rsbnum: 5; totalwords: 152; datawords: 122; ecnum: 15), (rsbnum: 4; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 14; totalwords: 76; datawords: 48; ecnum: 14), (rsbnum: 11; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 14; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 16; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 14; totalwords: 46; datawords: 16; ecnum: 15), // version 24 (rsbs[153]~rsbs[160]) (rsbnum: 6; totalwords: 147; datawords: 117; ecnum: 15), (rsbnum: 4; totalwords: 148; datawords: 118; ecnum: 15), (rsbnum: 6; totalwords: 73; datawords: 45; ecnum: 14), (rsbnum: 14; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 11; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 16; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 30; totalwords: 46; datawords: 16; ecnum: 15), (rsbnum: 2; totalwords: 47; datawords: 17; ecnum: 15), // version 25 (rsbs[161]~rsbs[168]) (rsbnum: 8; totalwords: 132; datawords: 106; ecnum: 13), (rsbnum: 4; totalwords: 133; datawords: 107; ecnum: 13), (rsbnum: 8; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 13; totalwords: 76; datawords: 48; ecnum: 14), (rsbnum: 7; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 22; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 22; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 13; totalwords: 46; datawords: 16; ecnum: 15), // version 26 (rsbs[169]~rsbs[176]) (rsbnum: 10; totalwords: 142; datawords: 114; ecnum: 14), (rsbnum: 2; totalwords: 143; datawords: 115; ecnum: 14), (rsbnum: 19; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 4; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 28; totalwords: 50; datawords: 22; ecnum: 14), (rsbnum: 6; totalwords: 51; datawords: 23; ecnum: 14), (rsbnum: 33; totalwords: 46; datawords: 16; ecnum: 15), (rsbnum: 4; totalwords: 47; datawords: 17; ecnum: 15), // version 27 (rsbs[177]~rsbs[184]) (rsbnum: 8; totalwords: 152; datawords: 122; ecnum: 15), (rsbnum: 4; totalwords: 153; datawords: 123; ecnum: 15), (rsbnum: 22; totalwords: 73; datawords: 45; ecnum: 14), (rsbnum: 3; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 8; totalwords: 53; datawords: 23; ecnum: 15), (rsbnum: 26; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 12; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 28; totalwords: 46; datawords: 16; ecnum: 15), // version 28 (rsbs[185]~rsbs[192]) (rsbnum: 3; totalwords: 147; datawords: 117; ecnum: 15), (rsbnum: 10; totalwords: 148; datawords: 118; ecnum: 15), (rsbnum: 3; totalwords: 73; datawords: 45; ecnum: 14), (rsbnum: 23; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 4; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 31; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 11; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 31; totalwords: 46; datawords: 16; ecnum: 15), // version 29 (rsbs[193]~rsbs[200]) (rsbnum: 7; totalwords: 146; datawords: 116; ecnum: 15), (rsbnum: 7; totalwords: 147; datawords: 117; ecnum: 15), (rsbnum: 21; totalwords: 73; datawords: 45; ecnum: 14), (rsbnum: 7; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 1; totalwords: 53; datawords: 23; ecnum: 15), (rsbnum: 37; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 19; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 26; totalwords: 46; datawords: 16; ecnum: 15), // version 30 (rsbs[201]~rsbs[208]) (rsbnum: 5; totalwords: 145; datawords: 115; ecnum: 15), (rsbnum: 10; totalwords: 146; datawords: 116; ecnum: 15), (rsbnum: 19; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 10; totalwords: 76; datawords: 48; ecnum: 14), (rsbnum: 15; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 25; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 23; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 25; totalwords: 46; datawords: 16; ecnum: 15), // version 31 (rsbs[209]~rsbs[216]) (rsbnum: 13; totalwords: 145; datawords: 115; ecnum: 15), (rsbnum: 3; totalwords: 146; datawords: 116; ecnum: 15), (rsbnum: 2; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 29; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 42; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 1; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 23; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 28; totalwords: 46; datawords: 16; ecnum: 15), // version 32 (rsbs[217]~rsbs[223]) (rsbnum: 17; totalwords: 145; datawords: 115; ecnum: 15), (rsbnum: 10; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 23; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 10; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 35; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 19; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 35; totalwords: 46; datawords: 16; ecnum: 15), // version 33 (rsbs[224]~rsbs[231]) (rsbnum: 17; totalwords: 145; datawords: 115; ecnum: 15), (rsbnum: 1; totalwords: 146; datawords: 116; ecnum: 15), (rsbnum: 14; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 21; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 29; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 19; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 11; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 46; totalwords: 46; datawords: 16; ecnum: 15), // version 34 (rsbs[232]~rsbs[239]) (rsbnum: 13; totalwords: 145; datawords: 115; ecnum: 15), (rsbnum: 6; totalwords: 146; datawords: 116; ecnum: 15), (rsbnum: 14; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 23; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 44; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 7; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 59; totalwords: 46; datawords: 16; ecnum: 15), (rsbnum: 1; totalwords: 47; datawords: 17; ecnum: 15), // version 35 (rsbs[240]~rsbs[247]) (rsbnum: 12; totalwords: 151; datawords: 121; ecnum: 15), (rsbnum: 7; totalwords: 152; datawords: 122; ecnum: 15), (rsbnum: 12; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 26; totalwords: 76; datawords: 48; ecnum: 14), (rsbnum: 39; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 14; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 22; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 41; totalwords: 46; datawords: 16; ecnum: 15), // version 36 (rsbs[248]~rsbs[255]) (rsbnum: 6; totalwords: 151; datawords: 121; ecnum: 15), (rsbnum: 14; totalwords: 152; datawords: 122; ecnum: 15), (rsbnum: 6; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 34; totalwords: 76; datawords: 48; ecnum: 14), (rsbnum: 46; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 10; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 2; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 64; totalwords: 46; datawords: 16; ecnum: 15), // version 37 (rsbs[256]~rsbs[263]) (rsbnum: 17; totalwords: 152; datawords: 122; ecnum: 15), (rsbnum: 4; totalwords: 153; datawords: 123; ecnum: 15), (rsbnum: 29; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 14; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 49; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 10; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 24; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 46; totalwords: 46; datawords: 16; ecnum: 15), // version 38 (rsbs[264]~rsbs[271]) (rsbnum: 4; totalwords: 152; datawords: 122; ecnum: 15), (rsbnum: 18; totalwords: 153; datawords: 123; ecnum: 15), (rsbnum: 13; totalwords: 74; datawords: 46; ecnum: 14), (rsbnum: 32; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 48; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 14; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 42; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 32; totalwords: 46; datawords: 16; ecnum: 15), // version 39 (rsbs[272]~rsbs[279]) (rsbnum: 20; totalwords: 147; datawords: 117; ecnum: 15), (rsbnum: 4; totalwords: 148; datawords: 118; ecnum: 15), (rsbnum: 40; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 7; totalwords: 76; datawords: 48; ecnum: 14), (rsbnum: 43; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 22; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 10; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 67; totalwords: 46; datawords: 16; ecnum: 15), // version 40 (rsbs[280]~rsbs[287]) (rsbnum: 19; totalwords: 148; datawords: 118; ecnum: 15), (rsbnum: 6; totalwords: 149; datawords: 119; ecnum: 15), (rsbnum: 18; totalwords: 75; datawords: 47; ecnum: 14), (rsbnum: 31; totalwords: 76; datawords: 48; ecnum: 14), (rsbnum: 34; totalwords: 54; datawords: 24; ecnum: 15), (rsbnum: 34; totalwords: 55; datawords: 25; ecnum: 15), (rsbnum: 20; totalwords: 45; datawords: 15; ecnum: 15), (rsbnum: 61; totalwords: 46; datawords: 16; ecnum: 15) ); nlens: array[0..2, 0..3] of Integer = ( (10, 9, 8, 8), (12, 11, 16, 10), (14, 13, 16, 12) ); aplocs: array[1..40, 0..6] of Integer = ( (0, 0, 0, 0, 0, 0, 0), (6, 18, 0, 0, 0, 0, 0), (6, 22, 0, 0, 0, 0, 0), (6, 26, 0, 0, 0, 0, 0), (6, 30, 0, 0, 0, 0, 0), (6, 34, 0, 0, 0, 0, 0), (6, 22, 38, 0, 0, 0, 0), (6, 24, 42, 0, 0, 0, 0), (6, 26, 46, 0, 0, 0, 0), (6, 28, 50, 0, 0, 0, 0), (6, 30, 54, 0, 0, 0, 0), (6, 32, 58, 0, 0, 0, 0), (6, 34, 62, 0, 0, 0, 0), (6, 26, 46, 66, 0, 0, 0), (6, 26, 48, 70, 0, 0, 0), (6, 26, 50, 74, 0, 0, 0), (6, 30, 54, 78, 0, 0, 0), (6, 30, 56, 82, 0, 0, 0), (6, 30, 58, 86, 0, 0, 0), (6, 34, 62, 90, 0, 0, 0), (6, 28, 50, 72, 94, 0, 0), (6, 26, 50, 74, 98, 0, 0), (6, 30, 54, 78, 102, 0, 0), (6, 28, 54, 80, 106, 0, 0), (6, 32, 58, 84, 110, 0, 0), (6, 30, 58, 86, 114, 0, 0), (6, 34, 62, 90, 118, 0, 0), (6, 26, 50, 74, 98, 122, 0), (6, 30, 54, 78, 102, 126, 0), (6, 26, 52, 78, 104, 130, 0), (6, 30, 56, 82, 108, 134, 0), (6, 34, 60, 86, 112, 138, 0), (6, 30, 58, 86, 114, 142, 0), (6, 34, 62, 90, 118, 146, 0), (6, 30, 54, 78, 102, 126, 150), (6, 24, 50, 76, 102, 128, 154), (6, 28, 54, 80, 106, 132, 158), (6, 32, 58, 84, 110, 136, 162), (6, 26, 54, 82, 110, 138, 166), (6, 30, 58, 86, 114, 142, 170) ); var i, j, k: Integer; { vertable 初期化用データ領域 } ecls: array[1..QR_VER_MAX, 0..QR_ECL_MAX - 1] of QR_ECLEVEL; begin { ecls: array[1..QR_VER_MAX, 0..QR_ECL_MAX - 1] of QR_ECLEVEL の初期化 } ZeroMemory(@ecls, SizeOf(ecls)); for i := 1 to QR_VER_MAX do begin for j := 0 to (QR_ECL_MAX - 1) do begin for k := 0 to (QR_EM_MAX - 1) do ecls[i][j].capacity[k] := capacities[i][j][k]; end; end; // version 1 ecls[1][0].datawords := 19; ecls[1][0].nrsb := 1; ecls[1][0].rsb[0] := rsbs[0]; ecls[1][1].datawords := 16; ecls[1][1].nrsb := 1; ecls[1][1].rsb[0] := rsbs[1]; ecls[1][2].datawords := 13; ecls[1][2].nrsb := 1; ecls[1][2].rsb[0] := rsbs[2]; ecls[1][3].datawords := 9; ecls[1][3].nrsb := 1; ecls[1][3].rsb[0] := rsbs[3]; // version 2 ecls[2][0].datawords := 34; ecls[2][0].nrsb := 1; ecls[2][0].rsb[0] := rsbs[4]; ecls[2][1].datawords := 28; ecls[2][1].nrsb := 1; ecls[2][1].rsb[0] := rsbs[5]; ecls[2][2].datawords := 22; ecls[2][2].nrsb := 1; ecls[2][2].rsb[0] := rsbs[6]; ecls[2][3].datawords := 16; ecls[2][3].nrsb := 1; ecls[2][3].rsb[0] := rsbs[7]; // version 3 ecls[3][0].datawords := 55; ecls[3][0].nrsb := 1; ecls[3][0].rsb[0] := rsbs[8]; ecls[3][1].datawords := 44; ecls[3][1].nrsb := 1; ecls[3][1].rsb[0] := rsbs[9]; ecls[3][2].datawords := 34; ecls[3][2].nrsb := 1; ecls[3][2].rsb[0] := rsbs[10]; ecls[3][3].datawords := 26; ecls[3][3].nrsb := 1; ecls[3][3].rsb[0] := rsbs[11]; // version 4 ecls[4][0].datawords := 80; ecls[4][0].nrsb := 1; ecls[4][0].rsb[0] := rsbs[12]; ecls[4][1].datawords := 64; ecls[4][1].nrsb := 1; ecls[4][1].rsb[0] := rsbs[13]; ecls[4][2].datawords := 48; ecls[4][2].nrsb := 1; ecls[4][2].rsb[0] := rsbs[14]; ecls[4][3].datawords := 36; ecls[4][3].nrsb := 1; ecls[4][3].rsb[0] := rsbs[15]; // version 5 ecls[5][0].datawords := 108; ecls[5][0].nrsb := 1; ecls[5][0].rsb[0] := rsbs[16]; ecls[5][1].datawords := 86; ecls[5][1].nrsb := 1; ecls[5][1].rsb[0] := rsbs[17]; ecls[5][2].datawords := 62; ecls[5][2].nrsb := 2; ecls[5][2].rsb[0] := rsbs[18]; ecls[5][2].rsb[1] := rsbs[19]; ecls[5][3].datawords := 46; ecls[5][3].nrsb := 2; ecls[5][3].rsb[0] := rsbs[20]; ecls[5][3].rsb[1] := rsbs[21]; // version 6 ecls[6][0].datawords := 136; ecls[6][0].nrsb := 1; ecls[6][0].rsb[0] := rsbs[22]; ecls[6][1].datawords := 108; ecls[6][1].nrsb := 1; ecls[6][1].rsb[0] := rsbs[23]; ecls[6][2].datawords := 76; ecls[6][2].nrsb := 1; ecls[6][2].rsb[0] := rsbs[24]; ecls[6][3].datawords := 60; ecls[6][3].nrsb := 1; ecls[6][3].rsb[0] := rsbs[25]; // version 7 ecls[7][0].datawords := 156; ecls[7][0].nrsb := 1; ecls[7][0].rsb[0] := rsbs[26]; ecls[7][1].datawords := 124; ecls[7][1].nrsb := 1; ecls[7][1].rsb[0] := rsbs[27]; ecls[7][2].datawords := 88; ecls[7][2].nrsb := 2; ecls[7][2].rsb[0] := rsbs[28]; ecls[7][2].rsb[1] := rsbs[29]; ecls[7][3].datawords := 66; ecls[7][3].nrsb := 2; ecls[7][3].rsb[0] := rsbs[30]; ecls[7][3].rsb[1] := rsbs[31]; // version 8 ecls[8][0].datawords := 194; ecls[8][0].nrsb := 1; ecls[8][0].rsb[0] := rsbs[32]; ecls[8][1].datawords := 154; ecls[8][1].nrsb := 2; ecls[8][1].rsb[0] := rsbs[33]; ecls[8][1].rsb[1] := rsbs[34]; ecls[8][2].datawords := 110; ecls[8][2].nrsb := 2; ecls[8][2].rsb[0] := rsbs[35]; ecls[8][2].rsb[1] := rsbs[36]; ecls[8][3].datawords := 86; ecls[8][3].nrsb := 2; ecls[8][3].rsb[0] := rsbs[37]; ecls[8][3].rsb[1] := rsbs[38]; // version 9 ecls[9][0].datawords := 232; ecls[9][0].nrsb := 1; ecls[9][0].rsb[0] := rsbs[39]; ecls[9][1].datawords := 182; ecls[9][1].nrsb := 2; ecls[9][1].rsb[0] := rsbs[40]; ecls[9][1].rsb[1] := rsbs[41]; ecls[9][2].datawords := 132; ecls[9][2].nrsb := 2; ecls[9][2].rsb[0] := rsbs[42]; ecls[9][2].rsb[1] := rsbs[43]; ecls[9][3].datawords := 100; ecls[9][3].nrsb := 2; ecls[9][3].rsb[0] := rsbs[44]; ecls[9][3].rsb[1] := rsbs[45]; // version 10 ecls[10][0].datawords := 274; ecls[10][0].nrsb := 2; ecls[10][0].rsb[0] := rsbs[46]; ecls[10][0].rsb[1] := rsbs[47]; ecls[10][1].datawords := 216; ecls[10][1].nrsb := 2; ecls[10][1].rsb[0] := rsbs[48]; ecls[10][1].rsb[1] := rsbs[49]; ecls[10][2].datawords := 154; ecls[10][2].nrsb := 2; ecls[10][2].rsb[0] := rsbs[50]; ecls[10][2].rsb[1] := rsbs[51]; ecls[10][3].datawords := 122; ecls[10][3].nrsb := 2; ecls[10][3].rsb[0] := rsbs[52]; ecls[10][3].rsb[1] := rsbs[53]; // version 11 ecls[11][0].datawords := 324; ecls[11][0].nrsb := 1; ecls[11][0].rsb[0] := rsbs[54]; ecls[11][1].datawords := 254; ecls[11][1].nrsb := 2; ecls[11][1].rsb[0] := rsbs[55]; ecls[11][1].rsb[1] := rsbs[56]; ecls[11][2].datawords := 180; ecls[11][2].nrsb := 2; ecls[11][2].rsb[0] := rsbs[57]; ecls[11][2].rsb[1] := rsbs[58]; ecls[11][3].datawords := 140; ecls[11][3].nrsb := 2; ecls[11][3].rsb[0] := rsbs[59]; ecls[11][3].rsb[1] := rsbs[60]; // version 12 ecls[12][0].datawords := 370; ecls[12][0].nrsb := 2; ecls[12][0].rsb[0] := rsbs[61]; ecls[12][0].rsb[1] := rsbs[62]; ecls[12][1].datawords := 290; ecls[12][1].nrsb := 2; ecls[12][1].rsb[0] := rsbs[63]; ecls[12][1].rsb[1] := rsbs[64]; ecls[12][2].datawords := 206; ecls[12][2].nrsb := 2; ecls[12][2].rsb[0] := rsbs[65]; ecls[12][2].rsb[1] := rsbs[66]; ecls[12][3].datawords := 158; ecls[12][3].nrsb := 2; ecls[12][3].rsb[0] := rsbs[67]; ecls[12][3].rsb[1] := rsbs[68]; // version 13 ecls[13][0].datawords := 428; ecls[13][0].nrsb := 1; ecls[13][0].rsb[0] := rsbs[69]; ecls[13][1].datawords := 334; ecls[13][1].nrsb := 2; ecls[13][1].rsb[0] := rsbs[70]; ecls[13][1].rsb[1] := rsbs[71]; ecls[13][2].datawords := 244; ecls[13][2].nrsb := 2; ecls[13][2].rsb[0] := rsbs[72]; ecls[13][2].rsb[1] := rsbs[73]; ecls[13][3].datawords := 180; ecls[13][3].nrsb := 2; ecls[13][3].rsb[0] := rsbs[74]; ecls[13][3].rsb[1] := rsbs[75]; // version 14 ecls[14][0].datawords := 461; ecls[14][0].nrsb := 2; ecls[14][0].rsb[0] := rsbs[76]; ecls[14][0].rsb[1] := rsbs[77]; ecls[14][1].datawords := 365; ecls[14][1].nrsb := 2; ecls[14][1].rsb[0] := rsbs[78]; ecls[14][1].rsb[1] := rsbs[79]; ecls[14][2].datawords := 261; ecls[14][2].nrsb := 2; ecls[14][2].rsb[0] := rsbs[80]; ecls[14][2].rsb[1] := rsbs[81]; ecls[14][3].datawords := 197; ecls[14][3].nrsb := 2; ecls[14][3].rsb[0] := rsbs[82]; ecls[14][3].rsb[1] := rsbs[83]; // version 15 ecls[15][0].datawords := 523; ecls[15][0].nrsb := 2; ecls[15][0].rsb[0] := rsbs[84]; ecls[15][0].rsb[1] := rsbs[85]; ecls[15][1].datawords := 415; ecls[15][1].nrsb := 2; ecls[15][1].rsb[0] := rsbs[86]; ecls[15][1].rsb[1] := rsbs[87]; ecls[15][2].datawords := 295; ecls[15][2].nrsb := 2; ecls[15][2].rsb[0] := rsbs[88]; ecls[15][2].rsb[1] := rsbs[89]; ecls[15][3].datawords := 223; ecls[15][3].nrsb := 2; ecls[15][3].rsb[0] := rsbs[90]; ecls[15][3].rsb[1] := rsbs[91]; // version 16 ecls[16][0].datawords := 589; ecls[16][0].nrsb := 2; ecls[16][0].rsb[0] := rsbs[92]; ecls[16][0].rsb[1] := rsbs[93]; ecls[16][1].datawords := 453; ecls[16][1].nrsb := 2; ecls[16][1].rsb[0] := rsbs[94]; ecls[16][1].rsb[1] := rsbs[95]; ecls[16][2].datawords := 325; ecls[16][2].nrsb := 2; ecls[16][2].rsb[0] := rsbs[96]; ecls[16][2].rsb[1] := rsbs[97]; ecls[16][3].datawords := 253; ecls[16][3].nrsb := 2; ecls[16][3].rsb[0] := rsbs[98]; ecls[16][3].rsb[1] := rsbs[99]; // version 17 ecls[17][0].datawords := 647; ecls[17][0].nrsb := 2; ecls[17][0].rsb[0] := rsbs[100]; ecls[17][0].rsb[1] := rsbs[101]; ecls[17][1].datawords := 507; ecls[17][1].nrsb := 2; ecls[17][1].rsb[0] := rsbs[102]; ecls[17][1].rsb[1] := rsbs[103]; ecls[17][2].datawords := 367; ecls[17][2].nrsb := 2; ecls[17][2].rsb[0] := rsbs[104]; ecls[17][2].rsb[1] := rsbs[105]; ecls[17][3].datawords := 283; ecls[17][3].nrsb := 2; ecls[17][3].rsb[0] := rsbs[106]; ecls[17][3].rsb[1] := rsbs[107]; // version 18 ecls[18][0].datawords := 721; ecls[18][0].nrsb := 2; ecls[18][0].rsb[0] := rsbs[108]; ecls[18][0].rsb[1] := rsbs[109]; ecls[18][1].datawords := 563; ecls[18][1].nrsb := 2; ecls[18][1].rsb[0] := rsbs[110]; ecls[18][1].rsb[1] := rsbs[111]; ecls[18][2].datawords := 397; ecls[18][2].nrsb := 2; ecls[18][2].rsb[0] := rsbs[112]; ecls[18][2].rsb[1] := rsbs[113]; ecls[18][3].datawords := 313; ecls[18][3].nrsb := 2; ecls[18][3].rsb[0] := rsbs[114]; ecls[18][3].rsb[1] := rsbs[115]; // version 19 ecls[19][0].datawords := 795; ecls[19][0].nrsb := 2; ecls[19][0].rsb[0] := rsbs[116]; ecls[19][0].rsb[1] := rsbs[117]; ecls[19][1].datawords := 627; ecls[19][1].nrsb := 2; ecls[19][1].rsb[0] := rsbs[118]; ecls[19][1].rsb[1] := rsbs[119]; ecls[19][2].datawords := 445; ecls[19][2].nrsb := 2; ecls[19][2].rsb[0] := rsbs[120]; ecls[19][2].rsb[1] := rsbs[121]; ecls[19][3].datawords := 341; ecls[19][3].nrsb := 2; ecls[19][3].rsb[0] := rsbs[122]; ecls[19][3].rsb[1] := rsbs[123]; // version 20 ecls[20][0].datawords := 861; ecls[20][0].nrsb := 2; ecls[20][0].rsb[0] := rsbs[124]; ecls[20][0].rsb[1] := rsbs[125]; ecls[20][1].datawords := 669; ecls[20][1].nrsb := 2; ecls[20][1].rsb[0] := rsbs[126]; ecls[20][1].rsb[1] := rsbs[127]; ecls[20][2].datawords := 485; ecls[20][2].nrsb := 2; ecls[20][2].rsb[0] := rsbs[128]; ecls[20][2].rsb[1] := rsbs[129]; ecls[20][3].datawords := 385; ecls[20][3].nrsb := 2; ecls[20][3].rsb[0] := rsbs[130]; ecls[20][3].rsb[1] := rsbs[131]; // version 21 ecls[21][0].datawords := 932; ecls[21][0].nrsb := 2; ecls[21][0].rsb[0] := rsbs[132]; ecls[21][0].rsb[1] := rsbs[133]; ecls[21][1].datawords := 714; ecls[21][1].nrsb := 1; ecls[21][1].rsb[0] := rsbs[134]; ecls[21][2].datawords := 512; ecls[21][2].nrsb := 2; ecls[21][2].rsb[0] := rsbs[135]; ecls[21][2].rsb[1] := rsbs[136]; ecls[21][3].datawords := 406; ecls[21][3].nrsb := 2; ecls[21][3].rsb[0] := rsbs[137]; ecls[21][3].rsb[1] := rsbs[138]; // version 22 ecls[22][0].datawords := 1006; ecls[22][0].nrsb := 2; ecls[22][0].rsb[0] := rsbs[139]; ecls[22][0].rsb[1] := rsbs[140]; ecls[22][1].datawords := 782; ecls[22][1].nrsb := 1; ecls[22][1].rsb[0] := rsbs[141]; ecls[22][2].datawords := 568; ecls[22][2].nrsb := 2; ecls[22][2].rsb[0] := rsbs[142]; ecls[22][2].rsb[1] := rsbs[143]; ecls[22][3].datawords := 442; ecls[22][3].nrsb := 1; ecls[22][3].rsb[0] := rsbs[144]; // version 23 ecls[23][0].datawords := 1094; ecls[23][0].nrsb := 2; ecls[23][0].rsb[0] := rsbs[145]; ecls[23][0].rsb[1] := rsbs[146]; ecls[23][1].datawords := 860; ecls[23][1].nrsb := 2; ecls[23][1].rsb[0] := rsbs[147]; ecls[23][1].rsb[1] := rsbs[148]; ecls[23][2].datawords := 614; ecls[23][2].nrsb := 2; ecls[23][2].rsb[0] := rsbs[149]; ecls[23][2].rsb[1] := rsbs[150]; ecls[23][3].datawords := 464; ecls[23][3].nrsb := 2; ecls[23][3].rsb[0] := rsbs[151]; ecls[23][3].rsb[1] := rsbs[152]; // version 24 ecls[24][0].datawords := 1174; ecls[24][0].nrsb := 2; ecls[24][0].rsb[0] := rsbs[153]; ecls[24][0].rsb[1] := rsbs[154]; ecls[24][1].datawords := 914; ecls[24][1].nrsb := 2; ecls[24][1].rsb[0] := rsbs[155]; ecls[24][1].rsb[1] := rsbs[156]; ecls[24][2].datawords := 664; ecls[24][2].nrsb := 2; ecls[24][2].rsb[0] := rsbs[157]; ecls[24][2].rsb[1] := rsbs[158]; ecls[24][3].datawords := 514; ecls[24][3].nrsb := 2; ecls[24][3].rsb[0] := rsbs[159]; ecls[24][3].rsb[1] := rsbs[160]; // version 25 ecls[25][0].datawords := 1276; ecls[25][0].nrsb := 2; ecls[25][0].rsb[0] := rsbs[161]; ecls[25][0].rsb[1] := rsbs[162]; ecls[25][1].datawords := 1000; ecls[25][1].nrsb := 2; ecls[25][1].rsb[0] := rsbs[163]; ecls[25][1].rsb[1] := rsbs[164]; ecls[25][2].datawords := 718; ecls[25][2].nrsb := 2; ecls[25][2].rsb[0] := rsbs[165]; ecls[25][2].rsb[1] := rsbs[166]; ecls[25][3].datawords := 538; ecls[25][3].nrsb := 2; ecls[25][3].rsb[0] := rsbs[167]; ecls[25][3].rsb[1] := rsbs[168]; // version 26 ecls[26][0].datawords := 1370; ecls[26][0].nrsb := 2; ecls[26][0].rsb[0] := rsbs[169]; ecls[26][0].rsb[1] := rsbs[170]; ecls[26][1].datawords := 1062; ecls[26][1].nrsb := 2; ecls[26][1].rsb[0] := rsbs[171]; ecls[26][1].rsb[1] := rsbs[172]; ecls[26][2].datawords := 754; ecls[26][2].nrsb := 2; ecls[26][2].rsb[0] := rsbs[173]; ecls[26][2].rsb[1] := rsbs[174]; ecls[26][3].datawords := 596; ecls[26][3].nrsb := 2; ecls[26][3].rsb[0] := rsbs[175]; ecls[26][3].rsb[1] := rsbs[176]; // version 27 ecls[27][0].datawords := 1468; ecls[27][0].nrsb := 2; ecls[27][0].rsb[0] := rsbs[177]; ecls[27][0].rsb[1] := rsbs[178]; ecls[27][1].datawords := 1128; ecls[27][1].nrsb := 2; ecls[27][1].rsb[0] := rsbs[179]; ecls[27][1].rsb[1] := rsbs[180]; ecls[27][2].datawords := 808; ecls[27][2].nrsb := 2; ecls[27][2].rsb[0] := rsbs[181]; ecls[27][2].rsb[1] := rsbs[182]; ecls[27][3].datawords := 628; ecls[27][3].nrsb := 2; ecls[27][3].rsb[0] := rsbs[183]; ecls[27][3].rsb[1] := rsbs[184]; // version 28 ecls[28][0].datawords := 1531; ecls[28][0].nrsb := 2; ecls[28][0].rsb[0] := rsbs[185]; ecls[28][0].rsb[1] := rsbs[186]; ecls[28][1].datawords := 1193; ecls[28][1].nrsb := 2; ecls[28][1].rsb[0] := rsbs[187]; ecls[28][1].rsb[1] := rsbs[188]; ecls[28][2].datawords := 871; ecls[28][2].nrsb := 2; ecls[28][2].rsb[0] := rsbs[189]; ecls[28][2].rsb[1] := rsbs[190]; ecls[28][3].datawords := 661; ecls[28][3].nrsb := 2; ecls[28][3].rsb[0] := rsbs[191]; ecls[28][3].rsb[1] := rsbs[192]; // version 29 ecls[29][0].datawords := 1631; ecls[29][0].nrsb := 2; ecls[29][0].rsb[0] := rsbs[193]; ecls[29][0].rsb[1] := rsbs[194]; ecls[29][1].datawords := 1267; ecls[29][1].nrsb := 2; ecls[29][1].rsb[0] := rsbs[195]; ecls[29][1].rsb[1] := rsbs[196]; ecls[29][2].datawords := 911; ecls[29][2].nrsb := 2; ecls[29][2].rsb[0] := rsbs[197]; ecls[29][2].rsb[1] := rsbs[198]; ecls[29][3].datawords := 701; ecls[29][3].nrsb := 2; ecls[29][3].rsb[0] := rsbs[199]; ecls[29][3].rsb[1] := rsbs[200]; // version 30 ecls[30][0].datawords := 1735; ecls[30][0].nrsb := 2; ecls[30][0].rsb[0] := rsbs[201]; ecls[30][0].rsb[1] := rsbs[202]; ecls[30][1].datawords := 1373; ecls[30][1].nrsb := 2; ecls[30][1].rsb[0] := rsbs[203]; ecls[30][1].rsb[1] := rsbs[204]; ecls[30][2].datawords := 985; ecls[30][2].nrsb := 2; ecls[30][2].rsb[0] := rsbs[205]; ecls[30][2].rsb[1] := rsbs[206]; ecls[30][3].datawords := 745; ecls[30][3].nrsb := 2; ecls[30][3].rsb[0] := rsbs[207]; ecls[30][3].rsb[1] := rsbs[208]; // version 31 ecls[31][0].datawords := 1843; ecls[31][0].nrsb := 2; ecls[31][0].rsb[0] := rsbs[209]; ecls[31][0].rsb[1] := rsbs[210]; ecls[31][1].datawords := 1455; ecls[31][1].nrsb := 2; ecls[31][1].rsb[0] := rsbs[211]; ecls[31][1].rsb[1] := rsbs[212]; ecls[31][2].datawords := 1033; ecls[31][2].nrsb := 2; ecls[31][2].rsb[0] := rsbs[213]; ecls[31][2].rsb[1] := rsbs[214]; ecls[31][3].datawords := 793; ecls[31][3].nrsb := 2; ecls[31][3].rsb[0] := rsbs[215]; ecls[31][3].rsb[1] := rsbs[216]; // version 32 ecls[32][0].datawords := 1955; ecls[32][0].nrsb := 1; ecls[32][0].rsb[0] := rsbs[217]; ecls[32][1].datawords := 1541; ecls[32][1].nrsb := 2; ecls[32][1].rsb[0] := rsbs[218]; ecls[32][1].rsb[1] := rsbs[219]; ecls[32][2].datawords := 1115; ecls[32][2].nrsb := 2; ecls[32][2].rsb[0] := rsbs[220]; ecls[32][2].rsb[1] := rsbs[221]; ecls[32][3].datawords := 845; ecls[32][3].nrsb := 2; ecls[32][3].rsb[0] := rsbs[222]; ecls[32][3].rsb[1] := rsbs[223]; // version 33 ecls[33][0].datawords := 2071; ecls[33][0].nrsb := 2; ecls[33][0].rsb[0] := rsbs[224]; ecls[33][0].rsb[1] := rsbs[225]; ecls[33][1].datawords := 1631; ecls[33][1].nrsb := 2; ecls[33][1].rsb[0] := rsbs[226]; ecls[33][1].rsb[1] := rsbs[227]; ecls[33][2].datawords := 1171; ecls[33][2].nrsb := 2; ecls[33][2].rsb[0] := rsbs[228]; ecls[33][2].rsb[1] := rsbs[229]; ecls[33][3].datawords := 901; ecls[33][3].nrsb := 2; ecls[33][3].rsb[0] := rsbs[230]; ecls[33][3].rsb[1] := rsbs[231]; // version 34 ecls[34][0].datawords := 2191; ecls[34][0].nrsb := 2; ecls[34][0].rsb[0] := rsbs[232]; ecls[34][0].rsb[1] := rsbs[233]; ecls[34][1].datawords := 1725; ecls[34][1].nrsb := 2; ecls[34][1].rsb[0] := rsbs[234]; ecls[34][1].rsb[1] := rsbs[235]; ecls[34][2].datawords := 1231; ecls[34][2].nrsb := 2; ecls[34][2].rsb[0] := rsbs[236]; ecls[34][2].rsb[1] := rsbs[237]; ecls[34][3].datawords := 961; ecls[34][3].nrsb := 2; ecls[34][3].rsb[0] := rsbs[238]; ecls[34][3].rsb[1] := rsbs[239]; // version 35 ecls[35][0].datawords := 2306; ecls[35][0].nrsb := 2; ecls[35][0].rsb[0] := rsbs[240]; ecls[35][0].rsb[1] := rsbs[241]; ecls[35][1].datawords := 1812; ecls[35][1].nrsb := 2; ecls[35][1].rsb[0] := rsbs[242]; ecls[35][1].rsb[1] := rsbs[243]; ecls[35][2].datawords := 1286; ecls[35][2].nrsb := 2; ecls[35][2].rsb[0] := rsbs[244]; ecls[35][2].rsb[1] := rsbs[245]; ecls[35][3].datawords := 986; ecls[35][3].nrsb := 2; ecls[35][3].rsb[0] := rsbs[246]; ecls[35][3].rsb[1] := rsbs[247]; // version 36 ecls[36][0].datawords := 2434; ecls[36][0].nrsb := 2; ecls[36][0].rsb[0] := rsbs[248]; ecls[36][0].rsb[1] := rsbs[249]; ecls[36][1].datawords := 1914; ecls[36][1].nrsb := 2; ecls[36][1].rsb[0] := rsbs[250]; ecls[36][1].rsb[1] := rsbs[251]; ecls[36][2].datawords := 1354; ecls[36][2].nrsb := 2; ecls[36][2].rsb[0] := rsbs[252]; ecls[36][2].rsb[1] := rsbs[253]; ecls[36][3].datawords := 1054; ecls[36][3].nrsb := 2; ecls[36][3].rsb[0] := rsbs[254]; ecls[36][3].rsb[1] := rsbs[255]; // version 37 ecls[37][0].datawords := 2566; ecls[37][0].nrsb := 2; ecls[37][0].rsb[0] := rsbs[256]; ecls[37][0].rsb[1] := rsbs[257]; ecls[37][1].datawords := 1992; ecls[37][1].nrsb := 2; ecls[37][1].rsb[0] := rsbs[258]; ecls[37][1].rsb[1] := rsbs[259]; ecls[37][2].datawords := 1426; ecls[37][2].nrsb := 2; ecls[37][2].rsb[0] := rsbs[260]; ecls[37][2].rsb[1] := rsbs[261]; ecls[37][3].datawords := 1096; ecls[37][3].nrsb := 2; ecls[37][3].rsb[0] := rsbs[262]; ecls[37][3].rsb[1] := rsbs[263]; // version 38 ecls[38][0].datawords := 2702; ecls[38][0].nrsb := 2; ecls[38][0].rsb[0] := rsbs[264]; ecls[38][0].rsb[1] := rsbs[265]; ecls[38][1].datawords := 2102; ecls[38][1].nrsb := 2; ecls[38][1].rsb[0] := rsbs[266]; ecls[38][1].rsb[1] := rsbs[267]; ecls[38][2].datawords := 1502; ecls[38][2].nrsb := 2; ecls[38][2].rsb[0] := rsbs[268]; ecls[38][2].rsb[1] := rsbs[269]; ecls[38][3].datawords := 1142; ecls[38][3].nrsb := 2; ecls[38][3].rsb[0] := rsbs[270]; ecls[38][3].rsb[1] := rsbs[271]; // version 39 ecls[39][0].datawords := 2812; ecls[39][0].nrsb := 2; ecls[39][0].rsb[0] := rsbs[272]; ecls[39][0].rsb[1] := rsbs[273]; ecls[39][1].datawords := 2216; ecls[39][1].nrsb := 2; ecls[39][1].rsb[0] := rsbs[274]; ecls[39][1].rsb[1] := rsbs[275]; ecls[39][2].datawords := 1582; ecls[39][2].nrsb := 2; ecls[39][2].rsb[0] := rsbs[276]; ecls[39][2].rsb[1] := rsbs[277]; ecls[39][3].datawords := 1222; ecls[39][3].nrsb := 2; ecls[39][3].rsb[0] := rsbs[278]; ecls[39][3].rsb[1] := rsbs[279]; // version 40 ecls[40][0].datawords := 2956; ecls[40][0].nrsb := 2; ecls[40][0].rsb[0] := rsbs[280]; ecls[40][0].rsb[1] := rsbs[281]; ecls[40][1].datawords := 2334; ecls[40][1].nrsb := 2; ecls[40][1].rsb[0] := rsbs[282]; ecls[40][1].rsb[1] := rsbs[283]; ecls[40][2].datawords := 1666; ecls[40][2].nrsb := 2; ecls[40][2].rsb[0] := rsbs[284]; ecls[40][2].rsb[1] := rsbs[285]; ecls[40][3].datawords := 1276; ecls[40][3].nrsb := 2; ecls[40][3].rsb[0] := rsbs[286]; ecls[40][3].rsb[1] := rsbs[287]; { vertable: array[0..QR_VER_MAX] of QR_VERTABLE 型番データ表の初期化 } ZeroMemory(@vertable, SizeOf(vertable)); k := 0; for i := 1 to QR_VER_MAX do begin vertable[i].version := i; if i in [10, 27] then Inc(k); for j := 0 to (QR_EM_MAX - 1) do vertable[i].nlen[j] := nlens[k][j]; for j := 0 to (QR_ECL_MAX - 1) do vertable[i].ecl[j] := ecls[i][j]; for j := 0 to (QR_APL_MAX - 1) do vertable[i].aploc[j] := aplocs[i][j]; end; // version 1 vertable[1].dimension := 21; vertable[1].totalwords := 26; vertable[1].remainedbits := 0; vertable[1].aplnum := 0; // version 2 vertable[2].dimension := 25; vertable[2].totalwords := 44; vertable[2].remainedbits := 7; vertable[2].aplnum := 2; // version 3 vertable[3].dimension := 29; vertable[3].totalwords := 70; vertable[3].remainedbits := 7; vertable[3].aplnum := 2; // version 4 vertable[4].dimension := 33; vertable[4].totalwords := 100; vertable[4].remainedbits := 7; vertable[4].aplnum := 2; // version 5 vertable[5].dimension := 37; vertable[5].totalwords := 134; vertable[5].remainedbits := 7; vertable[5].aplnum := 2; // version 6 vertable[6].dimension := 41; vertable[6].totalwords := 172; vertable[6].remainedbits := 7; vertable[6].aplnum := 2; // version 7 vertable[7].dimension := 45; vertable[7].totalwords := 196; vertable[7].remainedbits := 0; vertable[7].aplnum := 3; // version 8 vertable[8].dimension := 49; vertable[8].totalwords := 242; vertable[8].remainedbits := 0; vertable[8].aplnum := 3; // version 9 vertable[9].dimension := 53; vertable[9].totalwords := 292; vertable[9].remainedbits := 0; vertable[9].aplnum := 3; // version 10 vertable[10].dimension := 57; vertable[10].totalwords := 346; vertable[10].remainedbits := 0; vertable[10].aplnum := 3; // version 11 vertable[11].dimension := 61; vertable[11].totalwords := 404; vertable[11].remainedbits := 0; vertable[11].aplnum := 3; // version 12 vertable[12].dimension := 65; vertable[12].totalwords := 466; vertable[12].remainedbits := 0; vertable[12].aplnum := 3; // version 13 vertable[13].dimension := 69; vertable[13].totalwords := 532; vertable[13].remainedbits := 0; vertable[13].aplnum := 3; // version 14 vertable[14].dimension := 73; vertable[14].totalwords := 581; vertable[14].remainedbits := 3; vertable[14].aplnum := 4; // version 15 vertable[15].dimension := 77; vertable[15].totalwords := 655; vertable[15].remainedbits := 3; vertable[15].aplnum := 4; // version 16 vertable[16].dimension := 81; vertable[16].totalwords := 733; vertable[16].remainedbits := 3; vertable[16].aplnum := 4; // version 17 vertable[17].dimension := 85; vertable[17].totalwords := 815; vertable[17].remainedbits := 3; vertable[17].aplnum := 4; // version 18 vertable[18].dimension := 89; vertable[18].totalwords := 901; vertable[18].remainedbits := 3; vertable[18].aplnum := 4; // version 19 vertable[19].dimension := 93; vertable[19].totalwords := 991; vertable[19].remainedbits := 3; vertable[19].aplnum := 4; // version 20 vertable[20].dimension := 97; vertable[20].totalwords := 1085; vertable[20].remainedbits := 3; vertable[20].aplnum := 4; // version 21 vertable[21].dimension := 101; vertable[21].totalwords := 1156; vertable[21].remainedbits := 4; vertable[21].aplnum := 5; // version 22 vertable[22].dimension := 105; vertable[22].totalwords := 1258; vertable[22].remainedbits := 4; vertable[22].aplnum := 5; // version 23 vertable[23].dimension := 109; vertable[23].totalwords := 1364; vertable[23].remainedbits := 4; vertable[23].aplnum := 5; // version 24 vertable[24].dimension := 113; vertable[24].totalwords := 1474; vertable[24].remainedbits := 4; vertable[24].aplnum := 5; // version 25 vertable[25].dimension := 117; vertable[25].totalwords := 1588; vertable[25].remainedbits := 4; vertable[25].aplnum := 5; // version 26 vertable[26].dimension := 121; vertable[26].totalwords := 1706; vertable[26].remainedbits := 4; vertable[26].aplnum := 5; // version 27 vertable[27].dimension := 125; vertable[27].totalwords := 1828; vertable[27].remainedbits := 4; vertable[27].aplnum := 5; // version 28 vertable[28].dimension := 129; vertable[28].totalwords := 1921; vertable[28].remainedbits := 3; vertable[28].aplnum := 6; // version 29 vertable[29].dimension := 133; vertable[29].totalwords := 2051; vertable[29].remainedbits := 3; vertable[29].aplnum := 6; // version 30 vertable[30].dimension := 137; vertable[30].totalwords := 2185; vertable[30].remainedbits := 3; vertable[30].aplnum := 6; // version 31 vertable[31].dimension := 141; vertable[31].totalwords := 2323; vertable[31].remainedbits := 3; vertable[31].aplnum := 6; // version 32 vertable[32].dimension := 145; vertable[32].totalwords := 2465; vertable[32].remainedbits := 3; vertable[32].aplnum := 6; // version 33 vertable[33].dimension := 149; vertable[33].totalwords := 2611; vertable[33].remainedbits := 3; vertable[33].aplnum := 6; // version 34 vertable[34].dimension := 153; vertable[34].totalwords := 2761; vertable[34].remainedbits := 3; vertable[34].aplnum := 6; // version 35 vertable[35].dimension := 157; vertable[35].totalwords := 2876; vertable[35].remainedbits := 0; vertable[35].aplnum := 7; // version 36 vertable[36].dimension := 161; vertable[36].totalwords := 3034; vertable[36].remainedbits := 0; vertable[36].aplnum := 7; // version 37 vertable[37].dimension := 165; vertable[37].totalwords := 3196; vertable[37].remainedbits := 0; vertable[37].aplnum := 7; // version 38 vertable[38].dimension := 169; vertable[38].totalwords := 3362; vertable[38].remainedbits := 0; vertable[38].aplnum := 7; // version 39 vertable[39].dimension := 173; vertable[39].totalwords := 3532; vertable[39].remainedbits := 0; vertable[39].aplnum := 7; // version 40 vertable[40].dimension := 177; vertable[40].totalwords := 3706; vertable[40].remainedbits := 0; vertable[40].aplnum := 7; end; function TQRCode.isBlack(i, j: Integer): Boolean; begin Result := ((symbol[i][j] and QR_MM_BLACK) <> 0); end; function TQRCode.isData(i, j: Integer): Boolean; begin Result := ((symbol[i][j] and QR_MM_DATA) <> 0); end; function TQRCode.isFunc(i, j: Integer): Boolean; begin Result := ((symbol[i][j] and QR_MM_FUNC) <> 0); end; { ファイルをロードしてその内容をQRコードとして描画するメソッドです。} { ファイルのロードに成功しても常にファイルの内容をQRコードとして描画 } { 出来るとは限りませんので注意が必要です。} procedure TQRCode.LoadFromFile(const FileName: string); var MS: TMemoryStream; begin if not FileExists(FileName) then Exit; MS := TMemoryStream.Create; try MS.LoadFromFile(FileName); FLen := MS.Size; ReallocMem(FMemory, FLen 4); CopyMemory(FMemory, MS.Memory, FLen); FMemory[FLen] := Chr($00); FMemory[FLen 1] := Chr($00); FMemory[FLen 2] := Chr($00); FMemory[FLen 3] := Chr($00); Data2Code; PaintSymbolCode; // シンボルを描画する finally MS.Free; end; end; { メモリの内容を Count バイト分シンボルデータ領域へコピーしてQRコード } { として描画するメソッドです。メモリの内容を常にQRコードとして描画出来る } { とは限りませんので注意が必要です。} procedure TQRCode.LoadFromMemory(const Ptr: Pointer; Count: Integer); begin if (Ptr = nil) or (Count <= 0) then Exit; FLen := Count; ReallocMem(FMemory, FLen 4); CopyMemory(FMemory, Ptr, FLen); FMemory[FLen] := Chr($00); FMemory[FLen 1] := Chr($00); FMemory[FLen 2] := Chr($00); FMemory[FLen 3] := Chr($00); Data2Code; PaintSymbolCode; // シンボルを描画する end; procedure TQRCode.PaintSymbol; // イベントメソッド begin if Assigned(FOnPaintSymbol) then FOnPaintSymbol(Self, FWatch); // イベントハンドラの呼び出し end; procedure TQRCode.PaintedSymbol; // イベントメソッド begin if Assigned(FOnPaintedSymbol) then FOnPaintedSymbol(Self, FWatch); // イベントハンドラの呼び出し end; procedure TQRCode.PaintSymbolCode; var x, y: Integer; sl, st: Integer; sll, stt: Integer; asz, srh: Boolean; OrgFont: TFont; CmtUp: string; CmtDown: string; begin if FSymbolEnabled = False then // 一時的にシンボル表示を停止している状態 Exit; FSymbolDisped := False; CheckOffset; // シンボルデータ(Memory の)を Count 個に分割する。 CheckParity; // 連結モード(Mode = qrConnect)ならバリティ値を計算する。 icount := 1; // 現在表示しているシンボルのカウンタ値(1 ~ Count) PaintSymbol; // OnPaintSymbol イベントをここで発生 Picture.Bitmap.PixelFormat := pf32bit; // どの様な環境でもこの値に固定します。 if Picture.Bitmap.Empty = True then begin Picture.Bitmap.Width := Width; Picture.Bitmap.Height := Height; end; sll := FSymbolLeft; stt := FSymbolTop; if FMatch = False then begin if FAngle = 90 then begin FSymbolLeft := stt; FSymbolTop := Width - 1 - sll - SymbolHeightA 1; end else if FAngle = 180 then begin FSymbolLeft := Width - 1 - sll - SymbolWidthA 1; FSymbolTop := Height - 1 - stt - SymbolHeightA 1; end else if FAngle = 270 then begin FSymbolLeft := Height - 1 - stt - SymbolWidthA 1; FSymbolTop := sll; end; RotateBitmap(360 - FAngle); // -FAngle 度分回転する。 end; asz := AutoSize; srh := Stretch; AutoSize := False; Stretch := False; OrgFont := Canvas.Font; if FSymbolPicture = picBMP then Canvas.Font := FComFont; sl := FSymbolLeft; st := FSymbolTop; CmtUp := FCommentUp; CmtDown := FCommentDown; while icount <= FCount do begin FSymbolDisped := False; x := (icount - 1) mod FColumn; y := (icount - 1) div FColumn; FSymbolLeft := sl SymbolWidthS * x; FSymbolTop := st SymbolHeightS * y; if (FCount > 1) and (FNumbering in [nbrHead, nbrTail, nbrIfVoid]) then begin if FNumbering = nbrHead then begin if CmtUp = '' then FCommentUp := IntToStr(icount) else FCommentUp := IntToStr(icount) ' ' CmtUp; if CmtDown = '' then FCommentDown := IntToStr(icount) else FCommentDown := IntToStr(icount) ' ' CmtDown; end else if FNumbering = nbrTail then begin if CmtUp = '' then FCommentUp := IntToStr(icount) else FCommentUp := CmtUp ' ' IntToStr(icount); if CmtDown = '' then FCommentDown := IntToStr(icount) else FCommentDown := CmtDown ' ' IntToStr(icount); end else if FNumbering = nbrIfVoid then begin if CmtUp = '' then FCommentUp := IntToStr(icount); if CmtDown = '' then FCommentDown := IntToStr(icount); end; end; srclen := offsets[icount] - offsets[icount - 1]; if srclen > QR_SRC_MAX then // エラー Break; CopyMemory(@source, @FMemory[offsets[icount - 1]], srclen); if FSymbolPicture = picBMP then PaintSymbolCodeB // Picture.Bitmap への描画を行なう場合 else PaintSymbolCodeM; // Picture.Metafile への描画を行なう場合 if FSymbolDisped = False then // シンボルを表示出来なかった。 Break; Inc(icount); end; FCommentDown := CmtDown; FCommentUp := CmtUp; FSymbolTop := stt; FSymbolLeft := sll; if FSymbolPicture = picBMP then Canvas.Font := OrgFont; Stretch := srh; AutoSize := asz; if (FMatch = False) or (FSymbolDisped = True) then RotateBitmap(FAngle); // FAngle 度分回転する。 PaintedSymbol; // OnPaintedSymbol イベントをここで発生 if (FSymbolDisped = False) and (FClearOption = True) then begin if FSymbolDebug = False then Clear; // 画面をクリアーする。 end; end; procedure TQRCode.PaintSymbolCodeB; var Done: Integer; lx, ly, rx, ry: Integer; x, y: Integer; inBlack: Boolean; SX, SY: Integer; // シンボルの描画開始位置 dim: Integer; // 一辺のモジュール数 CmtUpWidth, CmtUpHeight: Integer; // 上部のコメント部分の大きさ CmtDownWidth, CmtDownHeight: Integer; // 下部のコメント部分の大きさ PositionUp, PositionDown: Integer; // 各コメントの表示開始位置 UpLimit, DownLimit: Integer; // 各コメントの表示開始の限界位置 begin if FEmode = -1 then Done := qrEncodeDataWordA // 自動符号化モード else Done := qrEncodeDataWordM; // 符号化モードが指定されている if Done = -1 then // 表示に失敗した Exit; qrComputeECWord; // 誤り訂正コード語を計算する qrMakeCodeWord; // 最終生成コード語を求める qrFillFunctionPattern; // シンボルに機能パターンを配置する qrFillCodeWord; // シンボルにコード語を配置する qrSelectMaskPattern; // シンボルにマスク処理を行う qrFillFormatInfo; // シンボルに型情報と形式情報を配置する { デバッグモードの場合 } if SymbolDebug = True then begin FSymbolDisped := True; Exit; end; { 各コメント部分の大きさを求める。} if FCommentUp <> '' then begin CmtUpWidth := Canvas.TextWidth(FCommentUp); CmtUpHeight := Canvas.TextHeight(FCommentUp); end else begin CmtUpWidth := 0; CmtUpHeight := 0; end; if FCommentDown <> '' then begin CmtDownWidth := Canvas.TextWidth(FCommentDown); CmtDownHeight := Canvas.TextHeight(FCommentDown); end else begin CmtDownWidth := 0; CmtDownHeight := 0; end; { コントロールのサイズをシンボルのサイズに合わせる場合 } if (FMatch = True) and (icount = 1) then begin Width := FSymbolLeft SymbolWidthA; Height := FSymbolTop SymbolHeightA; Picture.Bitmap.Width := Width; Picture.Bitmap.Height := Height; end; { Canvas の Pen を設定する。} Canvas.Pen.Color := FSymbolColor; Canvas.Pen.Style := psSolid; { シンボルの背景を描く。} if (FTransparent = False) and (icount = 1) then begin Canvas.Brush.Color := FBackColor; Canvas.Brush.Style := bsSolid; if FMatch = True then Canvas.FillRect(Rect(0, 0, FSymbolLeft SymbolWidthA, FSymbolTop SymbolHeightA)) else Canvas.FillRect(Rect(FSymbolLeft, FSymbolTop, FSymbolLeft SymbolWidthA, FSymbolTop SymbolHeightA)); end; { Canvas の Brush を設定する。} Canvas.Brush.Color := FSymbolColor; Canvas.Brush.Style := bsSolid; { シンボルを描く。} // シンボルの描画開始位置(X座標) SX := FSymbolLeft FSymbolSpaceLeft QR_DIM_SEP * FPxmag; // シンボルの描画開始位置(Y座標) SY := FSymbolTop FSymbolSpaceUp QR_DIM_SEP * FPxmag; dim := vertable[FVersion].dimension; // 一辺のモジュール数 for y := 0 to dim - 1 do begin lx := 0; ly := y * FPxmag; ry := ly FPxmag; inBlack := False; for x := 0 to dim - 1 do begin if (inBlack = False) and (isBlack(y, x) = True) then begin lx := x * FPxmag; inBlack := True; end else if (inBlack = True) and (isBlack(y, x) = False) then begin rx := x * FPxmag; Canvas.FillRect(Rect(SX lx, SY ly, SX rx, SY ry)); inBlack := False; end; end; if inBlack = True then begin rx := dim * FPxmag; Canvas.FillRect(Rect(SX lx, SY ly, SX rx, SY ry)); end; end; { シンボルの上下にコメントを描く場合の処理 } Canvas.Brush.Color := FBackColor; Canvas.Brush.Style := bsSolid; if FCommentUp <> '' then begin case FCommentUpLoc of locLeft: PositionUp := 0; locCenter: PositionUp := (FSymbolSpaceLeft SymbolWidth FSymbolSpaceRight - CmtUpWidth) div 2; locRight: PositionUp := FSymbolSpaceLeft SymbolWidth FSymbolSpaceRight - CmtUpWidth; else PositionUp := 0; end; if PositionUp < 0 then PositionUp := 0; UpLimit := FSymbolTop FSymbolSpaceUp - CmtUpHeight; y := FSymbolTop; if y > UpLimit then y := UpLimit; Canvas.TextOut(FSymbolLeft PositionUp, y, FCommentUp); end; if FCommentDown <> '' then begin case FCommentDownLoc of locLeft: PositionDown := 0; locCenter: PositionDown := (FSymbolSpaceLeft SymbolWidth FSymbolSpaceRight - CmtDownWidth) div 2; locRight: PositionDown := FSymbolSpaceLeft SymbolWidth FSymbolSpaceRight - CmtDownWidth; else PositionDown := 0; end; if PositionDown < 0 then PositionDown := 0; DownLimit := FSymbolTop FSymbolSpaceUp SymbolHeight; y := FSymbolTop FSymbolSpaceUp SymbolHeight FSymbolSpaceDown - CmtDownHeight; if y < DownLimit then y := DownLimit; Canvas.TextOut(FSymbolLeft PositionDown, y, FCommentDown); end; FSymbolDisped := True; end; procedure TQRCode.PaintSymbolCodeM; var Done: Integer; lx, ly, rx, ry: Integer; x, y: Integer; inBlack: Boolean; SX, SY: Integer; // シンボルの描画開始位置 dim: Integer; // 一辺のモジュール数 CmtUpWidth, CmtUpHeight: Integer; // 上部のコメント部分の大きさ CmtDownWidth, CmtDownHeight: Integer; // 下部のコメント部分の大きさ PositionUp, PositionDown: Integer; // 各コメントの表示開始位置 UpLimit, DownLimit: Integer; // 各コメントの表示開始の限界位置 begin if FEmode = -1 then Done := qrEncodeDataWordA // 自動符号化モード else Done := qrEncodeDataWordM; // 符号化モードが指定されている if Done = -1 then // 表示に失敗した begin if (icount > 1) and (SymbolDebug = False) then FMfCanvas.Free; // 開放する。 Exit; end; qrComputeECWord; // 誤り訂正コード語を計算する qrMakeCodeWord; // 最終生成コード語を求める qrFillFunctionPattern; // シンボルに機能パターンを配置する qrFillCodeWord; // シンボルにコード語を配置する qrSelectMaskPattern; // シンボルにマスク処理を行う qrFillFormatInfo; // シンボルに型情報と形式情報を配置する { デバッグモードの場合 } if SymbolDebug = True then begin FSymbolDisped := True; Exit; end; if icount = 1 then begin { コントロールのサイズをシンボルのサイズに合わせる。} Width := FSymbolLeft SymbolWidthA; Height := FSymbolTop SymbolHeightA; Picture.Metafile.Width := Width; Picture.Metafile.Height := Height; { メタファイルのキャンバスを用意する。 } FMfCanvas := TMetafileCanvas.Create(Picture.Metafile, GetDC(0)); { FMfCanvas の Pen と Brush を設定する。 } FMfCanvas.Pen.Color := FSymbolColor; FMfCanvas.Pen.Style := psSolid; FMfCanvas.Brush.Color := FBackColor; FMfCanvas.Brush.Style := bsSolid; { シンボルの背景を描く。 } FMfCanvas.FillRect(Rect(0, 0, Width, Height)); end; { シンボルを描く。} FMfCanvas.Pen.Color := FSymbolColor; FMfCanvas.Pen.Style := psSolid; FMfCanvas.Brush.Color := FSymbolColor; FMfCanvas.Brush.Style := bsSolid; // シンボルの描画開始位置(X座標) SX := FSymbolLeft FSymbolSpaceLeft QR_DIM_SEP * FPxmag; // シンボルの描画開始位置(Y座標) SY := FSymbolTop FSymbolSpaceUp QR_DIM_SEP * FPxmag; dim := vertable[FVersion].dimension; // 一辺のモジュール数 for y := 0 to dim - 1 do begin lx := 0; ly := y * FPxmag; ry := ly FPxmag; inBlack := False; for x := 0 to dim - 1 do begin if (inBlack = False) and (isBlack(y, x) = True) then begin lx := x * FPxmag; inBlack := True; end else if (inBlack = True) and (isBlack(y, x) = False) then begin rx := x * FPxmag; FMfCanvas.FillRect(Rect(SX lx, SY ly, SX rx, SY ry)); inBlack := False; end; end; if inBlack = True then begin rx := dim * FPxmag; FMfCanvas.FillRect(Rect(SX lx, SY ly, SX rx, SY ry)); end; end; { シンボルの上下にコメントを描く場合の処理 } FMfCanvas.Brush.Color := FBackColor; FMfCanvas.Brush.Style := bsSolid; FMfCanvas.Font := FComFont; { 各コメント部分の大きさを求める。} if FCommentUp <> '' then begin CmtUpWidth := FMfCanvas.TextWidth(FCommentUp); CmtUpHeight := FMfCanvas.TextHeight(FCommentUp); end else begin CmtUpWidth := 0; CmtUpHeight := 0; end; if FCommentDown <> '' then begin CmtDownWidth := FMfCanvas.TextWidth(FCommentDown); CmtDownHeight := FMfCanvas.TextHeight(FCommentDown); end else begin CmtDownWidth := 0; CmtDownHeight := 0; end; if FCommentUp <> '' then begin case FCommentUpLoc of locLeft: PositionUp := 0; locCenter: PositionUp := (FSymbolSpaceLeft SymbolWidth FSymbolSpaceRight - CmtUpWidth) div 2; locRight: PositionUp := FSymbolSpaceLeft SymbolWidth FSymbolSpaceRight - CmtUpWidth; else PositionUp := 0; end; if PositionUp < 0 then PositionUp := 0; UpLimit := FSymbolTop FSymbolSpaceUp - CmtUpHeight; y := FSymbolTop; if y > UpLimit then y := UpLimit; FMfCanvas.TextOut(FSymbolLeft PositionUp, y, FCommentUp); end; if FCommentDown <> '' then begin case FCommentDownLoc of locLeft: PositionDown := 0; locCenter: PositionDown := (FSymbolSpaceLeft SymbolWidth FSymbolSpaceRight - CmtDownWidth) div 2; locRight: PositionDown := FSymbolSpaceLeft SymbolWidth FSymbolSpaceRight - CmtDownWidth; else PositionDown := 0; end; if PositionDown < 0 then PositionDown := 0; DownLimit := FSymbolTop FSymbolSpaceUp SymbolHeight; y := FSymbolTop FSymbolSpaceUp SymbolHeight FSymbolSpaceDown - CmtDownHeight; if y < DownLimit then y := DownLimit; FMfCanvas.TextOut(FSymbolLeft PositionDown, y, FCommentDown); end; if icount = FCount then begin FMfCanvas.Free; // 開放して初めて描画される。 { なぜか1ピクセル分つぶれる(どこかの線がおかしくなる)ので表示後に } { 元にもどす。これは、M&I さんのご指摘により修正した部分です。} // 2001/08/05 Modify M&I Picture.Metafile.Width := Picture.Metafile.Width 1; Picture.Metafile.Height := Picture.Metafile.Height 1; end; FSymbolDisped := True; end; { 現在クリップボードにあるテキストデータでシンボルを描画するメソッドです。} procedure TQRCode.PasteFromClipboard; begin if Clipboard.HasFormat(CF_TEXT) then Code := Clipboard.AsText; end; { データコード語にビット列を追加する } procedure TQRCode.qrAddDataBits(n: Integer; w: Longword); begin { 上位ビットから順に処理(ビット単位で処理するので遅い) } while n > 0 do begin Dec(n); { ビット追加位置にデータの下位からnビットめをORする } dataword[dwpos] := dataword[dwpos] or (((w shr n) and 1) shl dwbit); { 次のビット追加位置に進む } Dec(dwbit); if dwbit < 0 then begin Inc(dwpos); dwbit := 7; end; end; end; { RSブロックごとに誤り訂正コード語を計算する } procedure TQRCode.qrComputeECWord; var i, j, k, m: Integer; ecwtop, dwtop, nrsb, rsbnum: Integer; dwlen, ecwlen: Integer; rsb: QR_RSBLOCK; e: Integer; begin { データコード語をRSブロックごとに読み出し、} { それぞれについて誤り訂正コード語を計算する } { RSブロックは長さによってnrsb種類に分かれ、} { それぞれの長さについてrsbnum個のブロックがある } dwtop := 0; ecwtop := 0; nrsb := vertable[FVersion].ecl[FEclevel].nrsb; for i := 0 to nrsb - 1 do begin { この長さのRSブロックの個数(rsbnum)と } { RSブロック内のデータコード語の長さ(dwlen)、} { 誤り訂正コード語の長さ(ecwlen)を求める } { また誤り訂正コード語の長さから、使われる } { 誤り訂正生成多項式(gftable[ecwlen])が選ばれる } rsb := vertable[FVersion].ecl[FEclevel].rsb[i]; rsbnum := rsb.rsbnum; dwlen := rsb.datawords; ecwlen := rsb.totalwords - rsb.datawords; { それぞれのRSブロックについてデータコード語を } { 誤り訂正生成多項式で除算し、結果を誤り訂正 } { コード語とする } for j := 0 to rsbnum - 1 do begin { RS符号計算用作業領域をクリアし、} { 当該RSブロックのデータコード語を } { 多項式係数とみなして作業領域に入れる } { (作業領域の大きさはRSブロックの } { データコード語と誤り訂正コード語の } { いずれか長いほうと同じだけ必要) } ZeroMemory(@rswork, SizeOf(rswork)); CopyMemory(@rswork, @dataword[dwtop], dwlen); { 多項式の除算を行う } { (各次数についてデータコード語の初項係数から } { 誤り訂正生成多項式への乗数を求め、多項式 } { どうしの減算により剰余を求めることをくり返す) } for k := 0 to dwlen - 1 do begin if rswork[0] = 0 then begin { 初項係数がゼロなので、各項係数を } { 左にシフトして次の次数に進む } for m := 0 to QR_RSD_MAX - 2 do rswork[m] := rswork[m 1]; rswork[QR_RSD_MAX - 1] := 0; Continue; end; { データコード語の初項係数(整数表現)から } { 誤り訂正生成多項式への乗数(べき表現)を求め、} { 残りの各項について剰余を求めるために } { データコード語の各項係数を左にシフトする } e := fac2exp[rswork[0]]; for m := 0 to QR_RSD_MAX - 2 do rswork[m] := rswork[m 1]; rswork[QR_RSD_MAX - 1] := 0; { 誤り訂正生成多項式の各項係数に上で求めた } { 乗数を掛け(べき表現の加算により求める)、} { データコード語の各項から引いて(整数表現の } { 排他的論理和により求める)、剰余を求める } for m := 0 to ecwlen - 1 do rswork[m] := rswork[m] xor exp2fac[(gftable[ecwlen][m] e) mod 255]; end; { 多項式除算の剰余を当該RSブロックの } { 誤り訂正コードとする } CopyMemory(@ecword[ecwtop], @rswork, ecwlen); { データコード語の読み出し位置と } { 誤り訂正コード語の書き込み位置を } { 次のRSブロック開始位置に移動する } Inc(dwtop, dwlen); Inc(ecwtop, ecwlen); end; end; end; { 入力データをモードに従って符号化する } function TQRCode.qrEncodeDataWordA: Integer; var p: PByte; n, m, len, mode: Integer; w: Longword; begin { エラーの場合の戻り値 } Result := -1; mode := -1; { データコード語を初期化する } qrInitDataWord; { 入力データを同じ文字クラスの部分に分割して } { それぞれの部分について符号化する } p := @source; len := qrGetSourceRegion(p, Integer(@source[srclen]) - Integer(p), mode); while len > 0 do begin { pからのlenバイトを符号化モードmodeで符号化する } { 入力データが長すぎる } if qrGetEncodedLength(mode, len) > qrRemainedDataBits then Exit; { モード指示子(4ビット)を追加する } qrAddDataBits(4, modeid[mode]); { 文字数指示子(8~16ビット)を追加する } { ビット数は型番とモードによって異なる } w := Longword(len); if mode = QR_EM_KANJI then w := w shr 1; qrAddDataBits(vertable[FVersion].nlen[mode], w); { データ本体を符号化する } case mode of QR_EM_NUMERIC: begin { 数字モード } { 3桁ずつ10ビットの2進数に変換する } { 余りは1桁なら4ビット、2桁なら7ビットにする } n := 0; w := 0; while len > 0 do begin Dec(len); w := w * 10 Longword(p^ - $30); // $30 = '0' Inc(p); { 3桁たまったら10ビットで追加する } Inc(n); if n >= 3 then begin qrAddDataBits(10, w); n := 0; w := 0; end; end; { 余りの桁を追加する } if n = 1 then qrAddDataBits(4, w) else if n = 2 then qrAddDataBits(7, w); end; QR_EM_ALNUM: begin { 英数字モード } { 2桁ずつ11ビットの2進数に変換する } { 余りは6ビットとして変換する } n := 0; w := 0; while len > 0 do begin Dec(len); w := w * 45 Longword(Longint(alnumtable[p^])); Inc(p); { 2桁たまったら11ビットで追加する } Inc(n); if n >= 2 then begin qrAddDataBits(11, w); n := 0; w := 0; end; end; { 余りの桁を追加する } if n = 1 then qrAddDataBits(6, w); end; QR_EM_8BIT: begin { 8ビットバイトモード } { 各バイトを直接8ビット値として追加する } while len > 0 do begin Dec(len); qrAddDataBits(8, p^); Inc(p); end; end; QR_EM_KANJI: begin { 漢字モード } { 2バイトを13ビットに変換して追加する } while len >= 2 do begin { 第1バイトの処理 } { $81~$9Fなら$81を引いて$C0を掛ける } { $E0~$EBなら$C1を引いて$C0を掛ける } if (p^ >= $81) and (p^ <= $9F) then w := (p^ - $81) * $C0 else // if (p^ >= $E0) and (p^ <= $EB) w := (p^ - $C1) * $C0; Inc(p); { 第2バイトの処理 } { $40を引いてから第1バイトの結果に加える } if ((p^ >= $40) and (p^ <= $7E)) or ((p^ >= $80) and (p^ <= $FC)) then w := w Longword(p^ - $40) else { JIS X 0208漢字の2バイトめでない } Exit; Inc(p); { 結果を13ビットの値として追加する } qrAddDataBits(13, w); Dec(len, 2); end; if len > 0 then { 末尾に余分なバイトがある } Exit; end; end; len := qrGetSourceRegion(p, Integer(@source[srclen]) - Integer(p), mode); end; { 終端パターンを追加する(最大4ビットの0) } n := qrRemainedDataBits; if n < 4 then begin qrAddDataBits(n, 0); n := 0; end else begin qrAddDataBits(4, 0); Dec(n, 4); end; { 末尾のデータコード語の全ビットが埋まっていなければ } { 余りを埋め草ビット(0)で埋める } m := n mod 8; if m > 0 then begin qrAddDataBits(m, 0); Dec(n, m); end; { 残りのデータコード語に埋め草コード語1,2を交互に埋める } w := PADWORD1; while n >= 8 do begin qrAddDataBits(8, w); if w = PADWORD1 then w := PADWORD2 else w := PADWORD1; Dec(n, 8); end; FEmodeR := mode; Result := 0; end; { 入力データをモードに従って符号化する } function TQRCode.qrEncodeDataWordM: Integer; var i: Integer; n, m: Integer; w: Longword; begin { エラーの場合の戻り値 } Result := -1; { データコード語を初期化する } qrInitDataWord; { 先頭からのsrclenバイトを符号化モードFEmodeで符号化する } { 入力データが長すぎる } if qrGetEncodedLength(FEmode, srclen) > qrRemainedDataBits then Exit; { モード指示子(4ビット)を追加する } qrAddDataBits(4, modeid[FEmode]); { 文字数指示子(8~16ビット)を追加する } { ビット数は型番とモードによって異なる } w := Longword(srclen); if (FEmode = QR_EM_KANJI) then w := w shr 1; qrAddDataBits(vertable[version].nlen[FEmode], w); { 入力データを符号化する } if FEmode = QR_EM_NUMERIC then begin { 数字モード } { 3桁ずつ10ビットの2進数に変換する } { 余りは1桁なら4ビット、2桁なら7ビットにする } n := 0; w := 0; i := 0; while i < srclen do begin if (source[i] < $30) or (source[i] > $39) then // $30 = '0', $39 = '9' Exit; // 数字でない w := w * 10 Longword(source[i] - $30); // $30 = '0' { 3桁たまったら10ビットで追加する } Inc(n); if n >= 3 then begin qrAddDataBits(10, w); n := 0; w := 0; end; Inc(i); end; { 余りの桁を追加する } if n = 1 then qrAddDataBits(4, w) else if n = 2 then qrAddDataBits(7, w); end else if FEmode = QR_EM_ALNUM then begin { 英数字モード } { 2桁ずつ11ビットの2進数に変換する } { 余りは6ビットとして変換する } n := 0; w := 0; i := 0; while i < srclen do begin if ((source[i] and $80) <> 0) or (alnumtable[source[i]] = -1) then Exit; // 符号化可能な英数字でない w := w * 45 Longword(Longint(alnumtable[source[i]])); { 2桁たまったら11ビットで追加する } Inc(n); if n >= 2 then begin qrAddDataBits(11, w); n := 0; w := 0; end; Inc(i); end; { 余りの桁を追加する } if n = 1 then qrAddDataBits(6, w); end else if FEmode = QR_EM_8BIT then begin { 8ビットバイトモード } { 各バイトを直接8ビット値として追加する } i := 0; while i < srclen do begin qrAddDataBits(8, source[i]); Inc(i); end; end else if FEmode = QR_EM_KANJI then begin { 漢字モード } { 2バイトを13ビットに変換して追加する } i := 0; while i < srclen - 1 do begin { 第1バイトの処理 } { $81~$9Fなら$81を引いて$C0を掛ける } { $E0~$EBなら$C1を引いて$C0を掛ける } if (source[i] >= $81) and (source[i] <= $9F) then w := (source[i] - $81) * $C0 else if (source[i] >= $E0) and (source[i] <= $EB) then w := (source[i] - $C1) * $C0 else Exit; // JIS X 0208漢字の1バイトめでない Inc(i); { 第2バイトの処理 } { 0x40を引いてから第1バイトの結果に加える } if ((source[i] >= $40) and (source[i] <= $7E)) or ((source[i] >= $80) and (source[i] <= $FC)) then w := w source[i] - $40 else Exit; // JIS X 0208漢字の2バイトめでない Inc(i); { 結果を13ビットの値として追加する } qrAddDataBits(13, w); end; if i < srclen then Exit; // 末尾に余分なバイトがある end; { 終端パターンを追加する(最大4ビットの0) } n := qrRemainedDataBits; if n < 4 then begin qrAddDataBits(n, 0); n := 0; end else begin qrAddDataBits(4, 0); Dec(n, 4); end; { 末尾のデータコード語の全ビットが埋まっていなければ } { 余りを埋め草ビット(0)で埋める } m := n mod 8; if m > 0 then begin qrAddDataBits(m, 0); Dec(n, m); end; { 残りのデータコード語に埋め草コード語1,2を交互に埋める } w := PADWORD1; while n >= 8 do begin qrAddDataBits(8, w); if w = PADWORD1 then w := PADWORD2 else w := PADWORD1; Dec(n, 8); end; Result := 0; end; { マスクパターンを評価し評価値を返す } function TQRCode.qrEvaluateMaskPattern: Longint; var i, j, m, n, dim: Integer; penalty: Longint; begin { 評価値をpenaltyに積算する } { マスクは符号化領域に対してのみ行うが } { 評価はシンボル全体について行われる } penalty := 0; dim := vertable[FVersion].dimension; { 特徴: 同色の行/列の隣接モジュール } { 評価条件: モジュール数 := (5 + i) } { 失点: 3 + i } for i := 0 to dim - 1 do begin n := 0; for j := 0 to dim - 1 do begin if (j > 0) and (isBlack(i, j) = isBlack(i, j - 1)) then Inc(n) // すぐ左と同色のモジュール、同色列の長さを1増やす else begin { 色が変わった } { 直前で終わった同色列の長さを評価する } if n >= 5 then penalty := penalty 3 (n - 5); n := 1; end; end; { 列が尽きた } { 直前で終わった同色列の長さを評価する } if n >= 5 then penalty := penalty 3 (n - 5); end; for i := 0 to dim - 1 do begin n := 0; for j := 0 to dim - 1 do begin if (j > 0) and (isBlack(j, i) = isBlack(j - 1, i)) then Inc(n) // すぐ上と同色のモジュール、同色列の長さを1増やす else begin { 色が変わった } { 直前で終わった同色列の長さを評価する } if n >= 5 then penalty := penalty 3 (n - 5); n := 1; end; end; { 列が尽きた } { 直前で終わった同色列の長さを評価する } if n >= 5 then penalty := penalty 3 (n - 5); end; { 特徴: 同色のモジュールブロック } { 評価条件: ブロックサイズ := 2×2 } { 失点: 3 } for i := 0 to dim - 2 do begin for j := 0 to dim - 2 do begin if ( (isBlack(i, j) = isBlack(i, j 1)) and (isBlack(i, j) = isBlack(i 1, j)) and (isBlack(i, j) = isBlack(i 1, j 1)) ) then Inc(penalty, 3); // 2×2の同色のブロックがあった end; end; { 特徴: 行/列における1:1:3:1:1比率(暗:明:暗:明:暗)のパターン } { 失点: 40 } { 前後はシンボル境界外か明モジュールである必要がある } { 2:2:6:2:2のようなパターンにも失点を与えるべきかは } { JIS規格からは読み取れない。ここでは与えていない } for i := 0 to dim - 1 do begin for j := 0 to dim - 7 do begin if ( ((j = 0) or (isBlack(i, j - 1) = False)) and (isBlack(i, j 0) = True) and (isBlack(i, j 1) = False) and (isBlack(i, j 2) = True) and (isBlack(i, j 3) = True) and (isBlack(i, j 4) = True) and (isBlack(i, j 5) = False) and (isBlack(i, j 6) = True) and ((j = dim - 7) or (isBlack(i, j 7) = False)) ) then Inc(penalty, 40); // パターンがあった end; end; for i := 0 to dim - 1 do begin for j := 0 to dim - 7 do begin if ( ((j = 0) or (isBlack(j - 1, i) = False)) and (isBlack(j 0, i) = True) and (isBlack(j 1, i) = False) and (isBlack(j 2, i) = True) and (isBlack(j 3, i) = True) and (isBlack(j 4, i) = True) and (isBlack(j 5, i) = False) and (isBlack(j 6, i) = True) and ((j = dim - 7) or (isBlack(j 7, i) = False)) ) then Inc(penalty, 40); // パターンがあった end; end; { 特徴: 全体に対する暗モジュールの占める割合 } { 評価条件: 50±(5×k)%~50±(5×(k+1))% } { 失点: 10×k } m := 0; n := 0; for i := 0 to dim - 1 do begin for j := 0 to dim - 1 do begin Inc(m); if isBlack(i, j) = True then Inc(n); end; end; penalty := penalty Abs((n * 100 div m) - 50) div 5 * 10; Result := penalty; end; { シンボルに符号化されたコード語を配置する } procedure TQRCode.qrFillCodeWord; var i, j: Integer; begin { シンボル右下隅から開始する } qrInitPosition; { コード語領域のすべてのバイトについて... } for i := 0 to vertable[FVersion].totalwords - 1 do begin { 最上位ビットから順に各ビットを調べ... } for j := 7 downto 0 do begin { そのビットが1なら黒モジュールを置く } if (codeword[i] and (1 shl j)) <> 0 then symbol[ypos][xpos] := symbol[ypos][xpos] or QR_MM_DATA; { 次のモジュール配置位置に移動する } qrNextPosition; end; end; end; { シンボルに形式情報と型番情報を配置する } procedure TQRCode.qrFillFormatInfo; var i, j, dim, fmt, modulo, xpos, ypos: Integer; v: Longint; begin dim := vertable[FVersion].dimension; { 形式情報を計算する } { 誤り訂正レベル2ビット(L:01, M:00, Q:11, H:10)と } { マスクパターン参照子3ビットからなる計5ビットに } { Bose-Chaudhuri-Hocquenghem(15,5)符号による } { 誤り訂正ビット10ビットを付加して15ビットとする } { (5ビットをxの次数14~10の多項式係数とみなして } { 多項式x^10 x^8 x^5 x^4 x^2 x 1(係数10100110111) } { で除算した剰余10ビットを誤り訂正ビットとする) } { さらにすべてのビットがゼロにならないように } { 101010000010010(0x5412)とXORをとる } fmt := ((FEclevel xor 1) shl 3) or FMasktypeR; modulo := fmt shl 10; for i := 14 downto 10 do begin if (modulo and (1 shl i)) = 0 then continue; modulo := modulo xor ($0537 shl (i - 10)); end; fmt := ((fmt shl 10) modulo) xor $5412; { 形式情報をシンボルに配置する } for i := 0 to 1 do begin for j := 0 to QR_FIN_MAX - 1 do begin if (fmt and (1 shl j)) = 0 then continue; xpos := (fmtinfopos[i][j].xpos dim) mod dim; ypos := (fmtinfopos[i][j].ypos dim) mod dim; symbol[ypos][xpos] := symbol[ypos][xpos] or QR_MM_BLACK; end; end; xpos := (fmtblackpos.xpos dim) mod dim; ypos := (fmtblackpos.ypos dim) mod dim; symbol[ypos][xpos] := symbol[ypos][xpos] or QR_MM_BLACK; { 型番情報が有効(型番7以上)なら } { 型番情報をシンボルに配置する } v := verinfo[FVersion]; if v <> -1 then begin for i := 0 to 1 do begin for j := 0 to QR_VIN_MAX - 1 do begin if (v and (1 shl j)) = 0 then continue; xpos := (verinfopos[i][j].xpos dim) mod dim; ypos := (verinfopos[i][j].ypos dim) mod dim; symbol[ypos][xpos] := symbol[ypos][xpos] or QR_MM_BLACK; end; end; end; end; { シンボルを初期化し、機能パターンを配置する } procedure TQRCode.qrFillFunctionPattern; var i, j, n, dim, xpos, ypos: Integer; x, y, x0, y0, xcenter, ycenter: Integer; begin { シンボルの1辺の長さを求める } dim := vertable[FVersion].dimension; { シンボル全体をクリアする } ZeroMemory(@symbol, SizeOf(symbol)); { 左上、右上、左下の隅に位置検出パターンを配置する } for i := 0 to QR_DIM_FINDER - 1 do begin for j := 0 to QR_DIM_FINDER - 1 do begin symbol[i][j] := finderpattern[i][j]; symbol[i][dim - 1 - j] := finderpattern[i][j]; symbol[dim - 1 - i][j] := finderpattern[i][j]; end; end; { 位置検出パターンの分離パターンを配置する } for i := 0 to QR_DIM_FINDER do begin symbol[i][QR_DIM_FINDER] := QR_MM_FUNC; symbol[QR_DIM_FINDER][i] := QR_MM_FUNC; symbol[i][dim - 1 - QR_DIM_FINDER] := QR_MM_FUNC; symbol[dim - 1 - QR_DIM_FINDER][i] := QR_MM_FUNC; symbol[dim - 1 - i][QR_DIM_FINDER] := QR_MM_FUNC; symbol[QR_DIM_FINDER][dim - 1 - i] := QR_MM_FUNC; end; { 位置合わせパターンを配置する } n := vertable[FVersion].aplnum; for i := 0 to n - 1 do begin for j := 0 to n - 1 do begin { 位置合わせパターンの中心と左上の座標を求める } ycenter := vertable[FVersion].aploc[i]; xcenter := vertable[FVersion].aploc[j]; y0 := ycenter - QR_DIM_ALIGN div 2; x0 := xcenter - QR_DIM_ALIGN div 2; if isFunc(ycenter, xcenter) = True then Continue; // 位置検出パターンと重なるときは配置しない for y := 0 to QR_DIM_ALIGN - 1 do begin for x := 0 to QR_DIM_ALIGN - 1 do symbol[y0 y][x0 x] := alignpattern[y][x]; end; end; end; { タイミングパターンを配置する } for i := QR_DIM_FINDER to dim - 1 - QR_DIM_FINDER - 1 do begin symbol[i][QR_DIM_TIMING] := QR_MM_FUNC; symbol[QR_DIM_TIMING][i] := QR_MM_FUNC; if (i and 1) = 0 then begin symbol[i][QR_DIM_TIMING] := symbol[i][QR_DIM_TIMING] or QR_MM_BLACK; symbol[QR_DIM_TIMING][i] := symbol[QR_DIM_TIMING][i] or QR_MM_BLACK; end; end; { 形式情報の領域を予約する } for i := 0 to 1 do begin for j := 0 to QR_FIN_MAX - 1 do begin xpos := (fmtinfopos[i][j].xpos dim) mod dim; ypos := (fmtinfopos[i][j].ypos dim) mod dim; symbol[ypos][xpos] := symbol[ypos][xpos] or QR_MM_FUNC; end; end; xpos := (fmtblackpos.xpos dim) mod dim; ypos := (fmtblackpos.ypos dim) mod dim; symbol[ypos][xpos] := symbol[ypos][xpos] or QR_MM_FUNC; { 型番情報が有効(型番7以上)なら } { 型番情報の領域を予約する } if verinfo[FVersion] <> -1 then begin for i := 0 to 1 do begin for j := 0 to QR_VIN_MAX - 1 do begin xpos := (verinfopos[i][j].xpos dim) mod dim; ypos := (verinfopos[i][j].ypos dim) mod dim; symbol[ypos][xpos] := symbol[ypos][xpos] or QR_MM_FUNC; end; end; end; end; { 特定のモードでlenバイト符号化したときのビット長を返す } function TQRCode.qrGetEncodedLength(mode: Integer; len: Integer): Integer; var n: Integer; begin { モード指示子と文字数指示子のサイズ } n := 4 vertable[FVersion].nlen[mode]; { 符号化モードごとのデータサイズ } case mode of QR_EM_NUMERIC: begin { 数字モード: 3桁ごとに10ビット } { (余りは1桁なら4ビット, 2桁なら7ビット) } n := n (len div 3) * 10; case (len mod 3) of 1: Inc(n, 4); 2: Inc(n, 7); end; end; QR_EM_ALNUM: begin { 英数字モード: 2桁ごとに11ビット } { (余りは1桁につき6ビット) } n := n (len div 2) * 11; if (len mod 2) = 1 then Inc(n, 6); end; QR_EM_8BIT: { 8ビットバイトモード: 1桁ごとに8ビット } n := n len * 8; QR_EM_KANJI: { 漢字モード: 1文字(2バイト)ごとに13ビット } n := n (len div 2) * 13; end; Result := n; end; { どの符号化モードで何バイト符号化すべきか求める } function TQRCode.qrGetSourceRegion(src: PByte; len: Integer; var mode: Integer): Integer; var n, m, cclass, ccnext: Integer; HasData: Boolean; begin Result := 0; { 入力データがない } { バイト数ゼロを返す } if len = 0 then Exit; { 残りの入力データの先頭から同じ符号化モードで } { 何バイトのデータを符号化すればよいか調べる } HasData := True; cclass := CharClassOf(src, len); n := 0; while HasData do begin { 同じ文字クラスの文字が何バイト続くか調べる } while (len > 0) and (CharClassOf(src, len) = cclass) do begin if cclass = QR_EM_KANJI then begin Inc(src, 2); Dec(len, 2); Inc(n, 2); end else begin Inc(src); Dec(len); Inc(n); end; end; if (len = 0) then begin { 入力データが尽きた } { 符号化モードとバイト数を返す } mode := cclass; Result := n; Exit; end; ccnext := CharClassOf(src, len); if (cclass = QR_EM_KANJI) or (ccnext = QR_EM_KANJI) then begin { 漢字クラスからそれ以外のクラスへ、または } { 漢字以外のクラスから漢字クラスへ変化した } { 符号化モードの切り替えが必要になるので } { ここまでの符号化モードとバイト数を返す } mode := cclass; Result := n; Exit; end; if cclass > ccnext then begin { 下位の文字クラスに変化した(8ビット→英数字, } { 8ビット→数字, 英数字→数字) } { ここで符号化モードを切り替えたほうが有利か } { 切り替えず続けたほうが有利か調べる } m := 0; while (len > 0) and (CharClassOf(src, len) = ccnext) do begin Inc(src); Dec(len); Inc(m); end; if (len > 0) and (CharClassOf(src, len) = cclass) then begin { 最初の文字クラスに戻った } { 符号化モードを切り替えてまた戻した場合と } { 切り替えなかった場合について } { 符号化ビット数の合計を比較する } if (qrGetEncodedLength(cclass, n) qrGetEncodedLength(ccnext, m) qrGetEncodedLength(cclass, 0)) < qrGetEncodedLength(cclass, n m) then begin { 切り替えたほうが短くなる } { 最初の文字クラスの部分について } { 符号化モードとバイト数を返す } mode := cclass; Result := n; Exit; end else begin { 切り替えないほうが短くなる } { 最初の文字クラスが続くとみなして } { カウントを続ける } Inc(n, m); Continue; end; end else begin { データが尽きたか別の文字クラスに変わった } { 符号化モードを切り替えた場合と } { 切り替えなかった場合について } { 符号化ビット数の合計を比較する } if (qrGetEncodedLength(cclass, n) qrGetEncodedLength(ccnext, m)) < qrGetEncodedLength(cclass, n m) then begin { 切り替えたほうが短くなる } { 最初の文字クラスの部分について } { 符号化モードとバイト数を返す } mode := cclass; Result := n; Exit; end else begin { 切り替えないほうが短くなる } { 最初の文字クラスが続くとみなして } { カウントを続ける } Inc(n, m); Continue; end; end; end else if cclass < ccnext then begin { より上位の文字クラスに変化した(数字→英数字, } { 数字→8ビット, 英数字→8ビット) } { ここで符号化モードを切り替えたほうが有利か、} { 先に切り替えておいたほうが有利か調べる } m := 0; while (len > 0) and (CharClassOf(src, len) = ccnext) do begin Inc(src); Dec(len); Inc(m); end; if (qrGetEncodedLength(cclass, n) qrGetEncodedLength(ccnext, m)) < qrGetEncodedLength(ccnext, n m) then begin { ここで切り替えたほうが短くなる } { 最初の文字クラスの部分について } { 符号化モードとバイト数を返す } mode := cclass; Result := n; Exit; end else begin { 先に切り替えておいたほうが短くなる } { 全体を後続の文字クラスと見なして } { 符号化モードとバイト数を返す } mode := ccnext; Result := n m; Exit; end; end; end; end; { データコード語を初期化する } procedure TQRCode.qrInitDataWord; begin { データコード語領域をゼロクリアする } ZeroMemory(@dataword, SizeOf(dataword)); { 追加位置をバイト0の最上位ビットにする } dwpos := 0; dwbit := 7; if FMode = qrConnect then begin { 連結モード指示子(4ビット)を追加する } qrAddDataBits(4, 3); // 0011B = 3 { シンボル列指示子(4ビット 4ビット)を追加する } qrAddDataBits(4, icount - 1); // 表示中のシンボルのカウンタ(1 ~ Count) qrAddDataBits(4, FCount - 1); // シンボルの表示個数 { パリティ値(8ビット)を追加する } qrAddDataBits(8, FParity); end; end; { モジュール配置の初期位置と配置方向を決める } procedure TQRCode.qrInitPosition; begin { シンボルの右下隅から配置を始める } xpos := vertable[FVersion].dimension - 1; ypos := xpos; { 最初の移動方向は左向き、次に上向き } xdir := -1; ydir := -1; end; { データコード語と誤り訂正コード語から最終的なコード語を作る } procedure TQRCode.qrMakeCodeWord; var i, j, k, cwtop, pos: Integer; dwlenmax, ecwlenmax: Integer; dwlen, ecwlen, nrsb: Integer; begin { RSブロックのサイズ種類数(nrsb)および } { 最大RSブロックのデータコード語数(dwlenmax)、} { 誤り訂正コード語数(ecwlenmax)を得る } nrsb := vertable[FVersion].ecl[FEclevel].nrsb; dwlenmax := vertable[FVersion].ecl[FEclevel].rsb[nrsb - 1].datawords; ecwlenmax := vertable[FVersion].ecl[FEclevel].rsb[nrsb - 1].totalwords - vertable[FVersion].ecl[FEclevel].rsb[nrsb - 1].datawords; { 各RSブロックから順にデータコード語を取り出し } { コード語領域(codeword)に追加する } cwtop := 0; for i := 0 to dwlenmax - 1 do begin pos := i; { RSブロックのサイズごとに処理を行う } for j := 0 to nrsb - 1 do begin dwlen := vertable[FVersion].ecl[FEclevel].rsb[j].datawords; { 同じサイズのRSブロックは順に処理する } for k := 0 to vertable[FVersion].ecl[FEclevel].rsb[j].rsbnum - 1 do begin { 各RSブロックのiバイトめのデータ } { コード語をコード語領域に追加する } { (すでにすべてのデータコード語を } { 取り出したRSブロックは飛ばす) } if i < dwlen then begin codeword[cwtop] := dataword[pos]; Inc(cwtop); end; { 次のRSブロックのiバイトめに進む } Inc(pos, dwlen); end; end; end; { 各RSブロックから順に誤り訂正コード語を取り出し } { コード語領域(codeword)に追加する } for i := 0 to ecwlenmax - 1 do begin pos := i; { RSブロックのサイズごとに処理を行う } for j := 0 to nrsb - 1 do begin ecwlen := vertable[FVersion].ecl[FEclevel].rsb[j].totalwords - vertable[FVersion].ecl[FEclevel].rsb[j].datawords; { 同じサイズのRSブロックは順に処理する } for k := 0 to vertable[FVersion].ecl[FEclevel].rsb[j].rsbnum - 1 do begin { 各RSブロックのiバイトめの誤り訂正 } { コード語をコード語領域に追加する } { (すでにすべての誤り訂正コード語を } { 取り出したRSブロックは飛ばす) } if i < ecwlen then begin codeword[cwtop] := ecword[pos]; Inc(cwtop); end; { 次のRSブロックのiバイトめに進む } Inc(pos, ecwlen); end; end; end; end; { 次のモジュール配置位置を決める } procedure TQRCode.qrNextPosition; begin repeat { xdir方向に1モジュール移動して } { xdirの向きを逆にする } { 右に移動したときはydir方向にも } { 1モジュール移動する } Inc(xpos, xdir); if xdir > 0 then Inc(ypos, ydir); xdir := -xdir; { y方向にシンボルをはみ出すようなら } { y方向ではなくx方向に2モジュール左に移動し、} { かつydirの向きを逆にする } { xposが縦のタイミングパターン上なら } { さらに1モジュール左に移動する } if (ypos < 0) or (ypos >= vertable[FVersion].dimension) then begin Dec(ypos, ydir); ydir := -ydir; Dec(xpos, 2); if xpos = QR_DIM_TIMING then Dec(xpos); end; { 新しい位置が機能パターン上なら } { それをよけて次の候補位置を探す } until isFunc(ypos, xpos) = False; end; { 生成されたQRコードシンボルを1個出力する } procedure TQRCode.qrOutputSymbol; var i, j, ix, jx, dim, imgdim: Integer; p: string; q: string; begin { 生成されたQRコードシンボルをモノクロ2値の } { アスキー形式Portable Bitmap(PBM)として出力する } { 縦横ともにFPxmagで指定した倍率で出力する } dim := vertable[FVersion].dimension; imgdim := (dim QR_DIM_SEP * 2) * FPxmag; // シンボルの大きさ(モジュール単位) { 分離パターンで囲んでシンボルを書く } for i := 0 to QR_DIM_SEP * FPxmag - 1 do begin p := ''; for j := 0 to imgdim - 1 do p := p ' 0'; FPBM.Add(p); end; for i := 0 to dim - 1 do begin for ix := 0 to FPxmag - 1 do begin p := ''; for j := 0 to QR_DIM_SEP * FPxmag - 1 do p := p ' 0'; for j := 0 to dim - 1 do begin if isBlack(i, j) = True then q := ' 1' else q := ' 0'; for jx := 0 to FPxmag - 1 do p := p q; end; for j := 0 to QR_DIM_SEP * FPxmag - 1 do p := p ' 0'; FPBM.Add(p); end; end; for i := 0 to QR_DIM_SEP * FPxmag - 1 do begin p := ''; for j := 0 to imgdim - 1 do p := p ' 0'; FPBM.Add(p); end; end; { QRコードシンボルを Count 個出力する } procedure TQRCode.qrOutputSymbols; var Done: Integer; dim, imgdim: Integer; p: string; begin { QRコードシンボルをモノクロ2値のアスキー形式 } { Portable Bitmap(PBM)として Count 個出力する } { 縦横ともにFPxmagで指定した倍率で出力する } FPBM.Clear; dim := vertable[FVersion].dimension; imgdim := (dim QR_DIM_SEP * 2) * FPxmag; // シンボルの大きさ(モジュール単位) p := 'P1'; FPBM.Add(p); if FMode = qrSingle then p := 'Single Mode (Count = ' else if FMode = qrConnect then p := 'Connect Mode (Count = ' else p := 'Plus Mode (Count = '; p := p IntToStr(FCount) ')'; FPBM.Add(p); p := IntToStr(imgdim); FPBM.Add(p ' ' p); icount := 1; // 現在符号化しているシンボルのカウンタ値(1 ~ Count) while icount <= FCount do begin srclen := offsets[icount 1] - offsets[icount]; if srclen > QR_SRC_MAX then // エラー Break; CopyMemory(@source, @FMemory[offsets[icount - 1]], srclen); if FEmode = -1 then Done := qrEncodeDataWordA // 自動符号化モード else Done := qrEncodeDataWordM; // 符号化モードが指定されている if Done = -1 then // 符号化に失敗した Break; qrComputeECWord; // 誤り訂正コード語を計算する qrMakeCodeWord; // 最終生成コード語を求める qrFillFunctionPattern; // シンボルに機能パターンを配置する qrFillCodeWord; // シンボルにコード語を配置する qrSelectMaskPattern; // シンボルにマスク処理を行う qrFillFormatInfo; // シンボルに型情報と形式情報を配置する FPBM.Add(''); // 改行する FPBM.Add(''); // 改行する qrOutputSymbol; // 生成されたQRコードシンボルを1個出力する Inc(icount); end; end; { データコード語の残りビット数を返す } function TQRCode.qrRemainedDataBits: Integer; begin Result := (vertable[FVersion].ecl[FEclevel].datawords - dwpos) * 8 - (7 - dwbit); end; { シンボルを最適なマスクパターンでマスクする } procedure TQRCode.qrSelectMaskPattern; var mask, xmask: Integer; penalty, xpenalty: Longint; begin if FMasktype >= 0 then begin { マスクパターンが引数で指定されていたので } { そのパターンでマスクして終了 } qrSetMaskPattern(FMasktype); Exit; end; { すべてのマスクパターンを評価する } xmask := 0; xpenalty := -1; for mask := 0 to QR_MPT_MAX - 1 do begin { 当該マスクパターンでマスクして評価する } qrSetMaskPattern(mask); penalty := qrEvaluateMaskPattern; { 失点がこれまでより低かったら記録する } if (xpenalty = -1) or (penalty < xpenalty) then begin xmask := mask; xpenalty := penalty; end; end; { 失点が最低のパターンでマスクする } FMasktypeR := xmask; qrSetMaskPattern(xmask); end; { 指定した参照子のマスクパターンでシンボルをマスクする } procedure TQRCode.qrSetMaskPattern(mask: Integer); var i, j, dim: Integer; begin dim := vertable[FVersion].dimension; { 以前のマスクパターンをクリアし、} { 符号化済みデータを初期パターンとする } for i := 0 to dim - 1 do begin for j := 0 to dim - 1 do begin { 機能パターン領域の印字黒モジュールは残す } if isFunc(i, j) = True then Continue; { 符号化データ領域は符号化データの } { 黒モジュールを印字黒モジュールにする } if isData(i, j) = True then symbol[i][j] := symbol[i][j] or QR_MM_BLACK else symbol[i][j] := symbol[i][j] and (not QR_MM_BLACK); end; end; { i行j列のモジュールについて... } for i := 0 to dim - 1 do begin for j := 0 to dim - 1 do begin { 機能パターン領域(および形式情報、} { 型番情報)はマスク対象から除外する } if isFunc(i, j) = True then Continue; { 指定された条件を満たすモジュールを反転する } if ( ((mask = 0) and ((i j) mod 2 = 0)) or ((mask = 1) and (i mod 2 = 0)) or ((mask = 2) and (j mod 3 = 0)) or ((mask = 3) and ((i j) mod 3 = 0)) or ((mask = 4) and (((i div 2) (j div 3)) mod 2 = 0)) or ((mask = 5) and ((i * j) mod 2 (i * j) mod 3 = 0)) or ((mask = 6) and (((i * j) mod 2 (i * j) mod 3) mod 2 = 0)) or ((mask = 7) and (((i * j) mod 3 (i j) mod 2) mod 2 = 0)) ) then symbol[i][j] := symbol[i][j] xor QR_MM_BLACK; end; end; end; { 現在のプロパティの値でシンボルを再描画するメソッドです。} { シンボルの上に何か図形を描いた後でシンボルを再描画する } { 場合等に使用します。} procedure TQRCode.RepaintSymbol; begin PaintSymbolCode; end; procedure TQRCode.ReverseBitmap; type TTriple = packed record B, G, R: Byte; end; TTripleArray = array[0..40000000] of TTriple; PTripleArray = ^TTripleArray; TDWordArray = array[0..100000000] of DWORD; PDWordArray = ^TDWordArray; var NewBitmap: TBitmap; x, y, i: Integer; w, h: Integer; BitCount: Integer; DS: TDIBSection; OldBitmap: TBitmap; Bits: Byte; Index: Integer; SourceScanline, DestScanline: array of Pointer; begin if (Picture.Graphic = nil) or (FSymbolPicture <> picBMP) or (FReverse = False) then Exit; OldBitmap := (Picture.Graphic as TBitmap); OldBitmap.HandleType := bmDIB; { 不正なビットマップの可能性がある場合は、強制的に 24bit Color にします。} { この様な事は、画面の色数が 16bit Color の場合等によく発生します。} if OldBitmap.PixelFormat in [pfDevice, pfcustom] then OldBitmap.PixelFormat := pf24bit; GetObject(OldBitmap.Handle, SizeOf(TDIBSection), @DS); BitCount := DS.dsBmih.biBitCount; if not (BitCount in [1, 4, 8, 16, 24, 32]) then Exit; NewBitmap := TBitmap.Create; try w := OldBitmap.Width; h := OldBitmap.Height; NewBitmap.HandleType := bmDIB; NewBitmap.PixelFormat := OldBitmap.PixelFormat; NewBitmap.Width := w; NewBitmap.Height := h; NewBitmap.Palette := CopyPalette(OldBitmap.Palette); SetLength(SourceScanline, h); SetLength(DestScanline, h); for i := 0 to h - 1 do SourceScanline[i] := OldBitmap.Scanline[i]; for i := 0 to h - 1 do DestScanline[i] := NewBitmap.Scanline[i]; for y := 0 to h - 1 do begin for x := 0 to w - 1 do begin case Bitcount of 32: PDWordArray(DestScanline[y])^[x] := PDWordArray(SourceScanline[y])^[w - 1 - x]; 24: PTripleArray(DestScanline[y])^[x] := PTripleArray(SourceScanline[y])^[w - 1 - x]; 16: PWordArray(DestScanline[y])^[x] := PWordArray(SourceScanline[y])^[w - 1 - x]; 8: PByteArray(DestScanline[y])^[x] := PByteArray(SourceScanline[y])^[w - 1 - x]; 4: begin Index := w - 1 - x; Bits := PByteArray(SourceScanline[y])^[Index div 2]; Bits := (Bits shr (4 * (1 - Index mod 2))) and $0F; PByteArray(DestScanline[y])^[x div 2] := (PByteArray(DestScanline[y])^[x div 2] and not ($F0 shr (4 * (x mod 2)))) or (Bits shl (4 * (1 - x mod 2))); end; 1: begin Index := w - 1 - x; Bits := PByteArray(SourceScanline[y])^[Index div 8]; Bits := (Bits shr (7 - Index mod 8)) and $01; PByteArray(DestScanline[y])^[x div 8] := (PByteArray(DestScanline[y])^[x div 8] and not ($80 shr (x mod 8))) or (Bits shl (7 - x mod 8)); end; end; end; end; //Picture.Graphic := NewBitmap; Picture.Bitmap.width := NewBitmap.width; Picture.Bitmap.Height := NewBitmap.Height; Picture.Bitmap := NewBitmap; finally NewBitmap.Free; end; end; procedure TQRCode.RotateBitmap(Degree: Integer); type TTriple = packed record B, G, R: Byte; end; TTripleArray = array[0..40000000] of TTriple; PTripleArray = ^TTripleArray; TDWordArray = array[0..100000000] of DWORD; PDWordArray = ^TDWordArray; var NewBitmap: TBitmap; x, y, i: Integer; w, h: Integer; ww, hh: Integer; asz, srh: Boolean; BitCount: Integer; DS: TDIBSection; OldBitmap: TBitmap; Bits: Byte; Index: Integer; SourceScanline, DestScanline: array of Pointer; begin if (Picture.Graphic = nil) or (FSymbolPicture <> picBMP) then Exit; if ((Degree <> 90) and (Degree <> 180) and (Degree <> 270)) then begin ReverseBitmap; Exit; end; asz := AutoSize; srh := Stretch; AutoSize := False; Stretch := False; ww := Width; hh := Height; OldBitmap := (Picture.Graphic as TBitmap); OldBitmap.HandleType := bmDIB; { 不正なビットマップの可能性がある場合は、強制的に 24bit Color にします。} { この様な事は、画面の色数が 16bit Color の場合等によく発生します。} if OldBitmap.PixelFormat in [pfDevice, pfcustom] then OldBitmap.PixelFormat := pf24bit; GetObject(OldBitmap.Handle, SizeOf(TDIBSection), @DS); BitCount := DS.dsBmih.biBitCount; if not (BitCount in [1, 4, 8, 16, 24, 32]) then Exit; NewBitmap := TBitmap.Create; try if Degree = 180 then begin w := OldBitmap.Width; h := OldBitmap.Height; end else begin w := OldBitmap.Height; h := OldBitmap.Width; end; NewBitmap.HandleType := bmDIB; NewBitmap.PixelFormat := OldBitmap.PixelFormat; NewBitmap.Width := w; NewBitmap.Height := h; NewBitmap.Palette := CopyPalette(OldBitmap.Palette); if Degree = 90 then begin SetLength(SourceScanline, w); SetLength(DestScanline, h); for i := 0 to w - 1 do SourceScanline[i] := OldBitmap.Scanline[i]; for i := 0 to h - 1 do DestScanline[i] := NewBitmap.Scanline[i]; for y := 0 to h - 1 do begin for x := 0 to w - 1 do begin case Bitcount of 32: PDWordArray(DestScanline[y])^[x] := PDWordArray(SourceScanline[w - 1 - x])^[y]; 24: PTripleArray(DestScanline[y])^[x] := PTripleArray(SourceScanline[w - 1 - x])^[y]; 16: PWordArray(DestScanline[y])^[x] := PWordArray(SourceScanline[w - 1 - x])^[y]; 8: PByteArray(DestScanline[y])^[x] := PByteArray(SourceScanline[w - 1 - x])^[y]; 4: begin Index := y; Bits := PByteArray(SourceScanline[w - 1 - x])^[Index div 2]; Bits := (Bits shr (4 * (1 - Index mod 2))) and $0F; PByteArray(DestScanline[y])^[x div 2] := (PByteArray(DestScanline[y])^[x div 2] and not ($F0 shr (4 * (x mod 2)))) or (Bits shl (4 * (1 - x mod 2))); end; 1: begin Index := y; Bits := PByteArray(SourceScanline[w - 1 - x])^[Index div 8]; Bits := (Bits shr (7 - Index mod 8)) and $01; PByteArray(DestScanline[y])^[x div 8] := (PByteArray(DestScanline[y])^[x div 8] and not ($80 shr (x mod 8))) or (Bits shl (7 - x mod 8)); end; end; end; end; Width := hh; Height := ww; end else if Degree = 180 then begin SetLength(SourceScanline, h); SetLength(DestScanline, h); for i := 0 to h - 1 do SourceScanline[i] := OldBitmap.Scanline[i]; for i := 0 to h - 1 do DestScanline[i] := NewBitmap.Scanline[i]; for y := 0 to h - 1 do begin for x := 0 to w - 1 do begin case Bitcount of 32: PDWordArray(DestScanline[y])^[x] := PDWordArray(SourceScanline[h - 1 - y])^[w - 1 - x]; 24: PTripleArray(DestScanline[y])^[x] := PTripleArray(SourceScanline[h - 1 - y])^[w - 1 - x]; 16: PWordArray(DestScanline[y])^[x] := PWordArray(SourceScanline[h - 1 - y])^[w - 1 - x]; 8: PByteArray(DestScanline[y])^[x] := PByteArray(SourceScanline[h - 1 - y])^[w - 1 - x]; 4: begin Index := w - 1 - x; Bits := PByteArray(SourceScanline[h - 1 - y])^[Index div 2]; Bits := (Bits shr (4 * (1 - Index mod 2))) and $0F; PByteArray(DestScanline[y])^[x div 2] := (PByteArray(DestScanline[y])^[x div 2] and not ($F0 shr (4 * (x mod 2)))) or (Bits shl (4 * (1 - x mod 2))); end; 1: begin Index := w - 1 - x; Bits := PByteArray(SourceScanline[h - 1 - y])^[Index div 8]; Bits := (Bits shr (7 - Index mod 8)) and $01; PByteArray(DestScanline[y])^[x div 8] := (PByteArray(DestScanline[y])^[x div 8] and not ($80 shr (x mod 8))) or (Bits shl (7 - x mod 8)); end; end; end; end; end else if Degree = 270 then begin SetLength(SourceScanline, w); SetLength(DestScanline, h); for i := 0 to w - 1 do SourceScanline[i] := OldBitmap.Scanline[i]; for i := 0 to h - 1 do DestScanline[i] := NewBitmap.Scanline[i]; for y := 0 to h - 1 do begin for x := 0 to w - 1 do begin case Bitcount of 32: PDWordArray(DestScanline[y])^[x] := PDWordArray(SourceScanline[x])^[h - 1 - y]; 24: PTripleArray(DestScanline[y])^[x] := PTripleArray(SourceScanline[x])^[h - 1 - y]; 16: PWordArray(DestScanline[y])^[x] := PWordArray(SourceScanline[x])^[h - 1 - y]; 8: PByteArray(DestScanline[y])^[x] := PByteArray(SourceScanline[x])^[h - 1 - y]; 4: begin Index := h - 1 - y; Bits := PByteArray(SourceScanline[x])^[Index div 2]; Bits := (Bits shr (4 * (1 - Index mod 2))) and $0F; PByteArray(DestScanline[y])^[x div 2] := (PByteArray(DestScanline[y])^[x div 2] and not ($F0 shr (4 * (x mod 2)))) or (Bits shl (4 * (1 - x mod 2))); end; 1: begin Index := h - 1 - y; Bits := PByteArray(SourceScanline[x])^[Index div 8]; Bits := (Bits shr (7 - Index mod 8)) and $01; PByteArray(DestScanline[y])^[x div 8] := (PByteArray(DestScanline[y])^[x div 8] and not ($80 shr (x mod 8))) or (Bits shl (7 - x mod 8)); end; end; end; end; Width := hh; Height := ww; end; //Picture.Graphic := NewBitmap; Picture.Bitmap.width := NewBitmap.width; Picture.Bitmap.Height := NewBitmap.Height; Picture.Bitmap := NewBitmap; finally NewBitmap.Free; end; AutoSize := asz; Stretch := srh; Invalidate; ReverseBitmap; end; { 2001/07/29 Created by M&I from here } //メタファイルコピー手続き procedure TQRCode.SaveToClipAsWMF(const mf: TMetafile); var hMetafilePict: THandle; pMFPict: PMetafilePict; DC: THandle; Length: Integer; Bits: Pointer; h: HMETAFILE; begin DC := GetDC(0); try Length := GetWinMetaFileBits(mf.Handle, 0, nil, MM_ANISOTROPIC, DC); //Assertは論理式が成立しない場合に例外を発生させるため //処理を簡略化出来ることがある。 //代りに条件式でチェックすればOK //Assert(Length > 0); if Length > 0 then begin GetMem(Bits, Length); try GetWinMetaFileBits(mf.Handle, Length, Bits, MM_ANISOTROPIC, DC); h := SetMetafileBitsEx(Length, Bits); //Assert(h <> 0); if h <> 0 then begin try hMetafilePict := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Length); //Assert(hMetafilePict <> 0); if hMetafilePict <> 0 then begin try pMFPict := GlobalLock(hMetafilePict); pMFPict^.mm := MM_ANISOTROPIC; pMFPict^.xExt := mf.MMWidth; pMfPict^.yExt := mf.MMHeight; pMfPict^.hMF := h; GlobalUnlock(hMetafilePict); Clipboard.SetAsHandle(CF_METAFILEPICT, hMetafilePict); except GlobalFree(hMetafilePict); raise; end; end; except DeleteObject(h); raise; end; end; finally FreeMem(Bits); end; end; finally ReleaseDC(0, DC); end; end; { シンボルデータの内容をファイルとして保存するメソッドです。必ずしも } { シンボルデータの内容をQRコードとして表示している場合とは限りません。} procedure TQRCode.SaveToFile(const FileName: string); var MS: TMemoryStream; begin MS := TMemoryStream.Create; try MS.SetSize(FLen); CopyMemory(MS.Memory, FMemory, FLen); MS.SaveToFile(FileName); finally MS.Free; end; end; procedure TQRCode.SetAngle(const Value: Integer); begin if (Value = 0) or (Value = 90) or (Value = 180) or (Value = 270) then begin FAngle := Value; PaintSymbolCode; end; end; procedure TQRCode.SetBackColor(const Value: TColor); begin FBackColor := Value; PaintSymbolCode; end; procedure TQRCode.SetBinaryOperation(const Value: Boolean); begin if csDesigning in ComponentState then // IDE 内 Exit; FBinaryOperation := Value; FLen := Code2Data; PaintSymbolCode; // シンボルを描画する end; procedure TQRCode.SetClearOption(const Value: Boolean); begin if Value = False then FClearOption := Value else begin if FClearOption = False then begin FClearOption := Value; if FSymbolDisped = False then Clear; end; end; end; { ClipWatch プロパティを False から True にすると、クリップボードに } { 変化がなくとも必ず OnClipChange イベントが一回発生するので、この } { 最初のイベントをスキップする必要がある。} procedure TQRCode.SetClipWatch(const Value: Boolean); begin if (FClipWatch = False) and (Value = True) then FSkip := True else FSkip := False; FClipWatch := Value; UpdateClip; end; procedure TQRCode.SetCode(const Value: string); begin if csDesigning in ComponentState then // IDE 内 begin FCode := Value; PaintSymbolCode; Exit; end; ChangeCode; // OnChangeCode イベントをここで発生 FCode := Value; FLen := Code2Data; PaintSymbolCode; // シンボルを描画する ChangedCode; // OnChangedCode イベントをここで発生 end; procedure TQRCode.SetColumn(const Value: Integer); begin if (Value >= 1) and (Value <= QR_PLS_MAX) then // 1 ~ 1024 begin FColumn := Value; PaintSymbolCode; end; end; procedure TQRCode.SetComFont(const Value: TFont); begin if (Value <> nil) and (Value <> FComFont) then begin FComFont.Assign(Value); PaintSymbolCode; end; end; procedure TQRCode.SetCommentDown(const Value: string); begin FCommentDown := Value; PaintSymbolCode; end; procedure TQRCode.SetCommentDownLoc(const Value: TLocation); begin FCommentDownLoc := Value; if FCommentDown <> '' then PaintSymbolCode; end; procedure TQRCode.SetCommentUp(const Value: string); begin FCommentUp := Value; PaintSymbolCode; end; procedure TQRCode.SetCommentUpLoc(const Value: TLocation); begin FCommentUpLoc := Value; if FCommentUp <> '' then PaintSymbolCode; end; procedure TQRCode.SetCount(const Value: Integer); begin if (Value >= 1) and (Value <= QR_PLS_MAX) then // 1 ~ 1024 begin FCount := Value; PaintSymbolCode; end; end; procedure TQRCode.SetData(Index: Integer; const Value: Byte); begin if (Index < 0) or (Index >= FLen) then raise ERangeError.CreateFmt('%d is not within the valid range of %d..%d', [Index, 0, FLen - 1]); FMemory[Index] := Char(Value); FLen := Data2Code; PaintSymbolCode; // シンボルを描画する end; procedure TQRCode.SetEclevel(const Value: Integer); begin if Value in [0..QR_ECL_MAX - 1] then begin FEclevel := Value; PaintSymbolCode; end; end; procedure TQRCode.SetEmode(const Value: Integer); begin if (Value in [0..QR_EM_MAX - 1]) or (Value = -1) then begin FEmode := Value; FEmodeR := FEmode; PaintSymbolCode; end; end; procedure TQRCode.SetMasktype(const Value: Integer); begin if (Value in [0..QR_MPT_MAX - 1]) or (Value = -1) then begin FMasktype := Value; FMasktypeR := FMasktype; PaintSymbolCode; end; end; procedure TQRCode.SetMatch(const Value: Boolean); begin FMatch := Value; if FMatch = True then begin if FTransparent = True then FTransparent := False; end else FSymbolPicture := picBMP; PaintSymbolCode; end; procedure TQRCode.SetMode(const Value: TQRMode); begin if Value = qrSingle then FCount := 1 else if Value = qrConnect then begin if FCount < 2 then FCount := 2 else if FCount > QR_CNN_MAX then FCount := QR_CNN_MAX; end else if Value = qrPlus then begin if FCount < 2 then FCount := 2 else if FCount > QR_PLS_MAX then FCount := QR_PLS_MAX; end else Exit; FMode := Value; PaintSymbolCode; end; procedure TQRCode.SetNumbering(const Value: TNumbering); begin if Value in [nbrNone, nbrHead, nbrTail, nbrIfVoid] then begin FNumbering := Value; if FCount > 1 then PaintSymbolCode; end; end; procedure TQRCode.SetOnClipChange(const Value: TNotifyEvent); begin FOnClipChange := Value; UpdateClip; end; procedure TQRCode.SetPxmag(const Value: Integer); begin if Value in [1..10] then begin FPxmag := Value; PaintSymbolCode; end; end; procedure TQRCode.SetReverse(const Value: Boolean); begin FReverse := Value; PaintSymbolCode; end; procedure TQRCode.SetSymbolColor(const Value: TColor); begin FSymbolColor := Value; PaintSymbolCode; end; procedure TQRCode.SetSymbolDebug(const Value: Boolean); begin FSymbolDebug := Value end; procedure TQRCode.SetSymbolEnabled(const Value: Boolean); begin if FSymbolEnabled <> Value then begin FSymbolEnabled := Value; if FSymbolEnabled = True then PaintSymbolCode; end; end; procedure TQRCode.SetSymbolLeft(const Value: Integer); begin FSymbolLeft := Value; PaintSymbolCode; end; procedure TQRCode.SetSymbolPicture(const Value: TPictures); begin if FMatch = False then FSymbolPicture := picBMP else begin FSymbolPicture := Value; PaintSymbolCode; end; end; procedure TQRCode.SetSymbolSpaceDown(const Value: Integer); begin FSymbolSpaceDown := Value; PaintSymbolCode; end; procedure TQRCode.SetSymbolSpaceLeft(const Value: Integer); begin FSymbolSpaceLeft := Value; PaintSymbolCode; end; procedure TQRCode.SetSymbolSpaceRight(const Value: Integer); begin FSymbolSpaceRight := Value; PaintSymbolCode; end; procedure TQRCode.SetSymbolSpaceUp(const Value: Integer); begin FSymbolSpaceUp := Value; PaintSymbolCode; end; procedure TQRCode.SetSymbolTop(const Value: Integer); begin FSymbolTop := Value; PaintSymbolCode; end; procedure TQRCode.SetTransparent(const Value: Boolean); begin FTransparent := Value; if FTransparent = True then begin if FMatch = True then FMatch := False; FSymbolPicture := picBMP; end; PaintSymbolCode; end; procedure TQRCode.SetVersion(const Value: Integer); begin if Value in [1..QR_VER_MAX] then begin FVersion := Value; PaintSymbolCode; end; end; procedure TQRCode.UpdateClip; begin if FRegistered = FClipWatch and Assigned(FOnClipChange) then Exit; FRegistered := not FRegistered; if FRegistered then FNextWindowHandle := SetClipboardViewer(FWindowHandle) else ChangeClipboardChain(FWindowHandle, FNextWindowHandle); end; procedure TQRCode.WndClipProc(var Message: TMessage); begin with Message do case Msg of WM_CHANGECBCHAIN: try with TWMChangeCBChain(Message) do if Remove = FNextWindowHandle then FNextWindowHandle := Next else if FNextWindowHandle <> 0 then SendMessage(FNextWindowHandle, Msg, wParam, lParam); except Application.HandleException(Self); end; WM_DRAWCLIPBOARD: try ClipChange; // OnClipChange イベントをここで発生 SendMessage(FNextWindowHandle, Msg, wParam, lParam); except Application.HandleException(Self); end; else Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam); end; end; end.
评论